FEAT: KANVAS customer
This commit is contained in:
parent
0a96c9c640
commit
7572127425
7 changed files with 477 additions and 350 deletions
|
@ -37,7 +37,7 @@
|
|||
}
|
||||
<div class="row mb-2 bg-dark text-white rounded-3 p-3">
|
||||
<div class="col">
|
||||
<h3>@Activity.Name - @Activity.Account</h3>
|
||||
<span class="h3">@Activity.Name</span> <span>(@Activity.Account)</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -58,9 +58,16 @@ else
|
|||
<label for="activityType" class="col-sm-2 col-form-label-sm">Ordre Type</label>
|
||||
<div class="col-sm-4">
|
||||
<InputSelect id="activityType" class="form-select bg-primary text-bg-primary" @bind-Value="@Activity.ActivityTypeEnum">
|
||||
@if (Kanvas)
|
||||
{
|
||||
<option value="canvas" selected>Kanvas</option>
|
||||
}
|
||||
else
|
||||
{
|
||||
<option value="">→ TAG MIG ←</option>
|
||||
<option value="onSite">Besøg</option>
|
||||
<option value="phone">Telefon</option>
|
||||
}
|
||||
</InputSelect>
|
||||
<ValidationMessage For="@(() => Activity.ActivityTypeEnum)"></ValidationMessage>
|
||||
</div>
|
||||
|
@ -68,6 +75,12 @@ else
|
|||
<label for="statusType" class="col-sm-2 col-form-label-sm">Status</label>
|
||||
<div class="col-sm-4">
|
||||
<InputSelect id="statusType" class="form-select bg-primary text-bg-primary" @bind-Value="@Activity.ActivityStatusEnum">
|
||||
@if (Kanvas)
|
||||
{
|
||||
<option value="canvas" selected>Kanvas</option>
|
||||
}
|
||||
else
|
||||
{
|
||||
<option value="noSale">Ingen salg</option>
|
||||
@if (!string.IsNullOrEmpty(Activity.VatNumber) && !string.IsNullOrWhiteSpace(Activity.Address1) && Company.HasFolded == 0)
|
||||
{
|
||||
|
@ -89,6 +102,7 @@ else
|
|||
<option value="quote">Tilbud</option>
|
||||
}
|
||||
}
|
||||
}
|
||||
</InputSelect>
|
||||
<ValidationMessage For="@(() => Activity.ActivityStatusEnum)"></ValidationMessage>
|
||||
@if (Activity.ActivityStatusEnum == "order")
|
||||
|
@ -156,6 +170,8 @@ else
|
|||
</div>
|
||||
</div>
|
||||
|
||||
@if (!Kanvas)
|
||||
{
|
||||
<div class="row g-2 mb-3">
|
||||
<div class="col-sm-3 d-grid mx-auto">
|
||||
@*
|
||||
|
@ -348,7 +364,9 @@ else
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</EditForm>
|
||||
|
||||
<div class="row mt-5 mb-2">
|
||||
<div class="col-sm-6">
|
||||
<a class="btn btn-warning" href="/advisor/customers/@Company.CompanyId">Kundekort <i class="bi-arrow-left"></i></a>
|
||||
|
|
|
@ -96,6 +96,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
private List<ProductInventoryView> CheckList { get; set; } = new();
|
||||
private InvoiceListView CompanyInvoices { get; set; } = new();
|
||||
private List<ReportItemView> Activities { get; set; } = new();
|
||||
private bool Kanvas { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Page initialization
|
||||
|
@ -114,6 +115,17 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
SalesRep = await UserInfo.GetUserInfo();
|
||||
// Fetch Customer from http
|
||||
Company = await CompanyRepo.GetCompanyById(CompanyId);
|
||||
if (Company.Account.StartsWith("KANVAS"))
|
||||
{
|
||||
Kanvas = true;
|
||||
|
||||
Activity.ActivityStatusEnum = "canvas";
|
||||
Activity.ActivityTypeEnum = "canvas";
|
||||
Activity.ActivityVisitEnum = "new";
|
||||
PoFormInvalid = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Company.HasFolded == 1)
|
||||
// Company has shut down
|
||||
Activity.OrderMessage = "BEMÆRK: CVR nummer er ophørt.";
|
||||
|
@ -126,11 +138,12 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
{
|
||||
Company.Phone = Company.Account[..8];
|
||||
}
|
||||
Activity.ActivityStatusEnum = "noSale";
|
||||
Activity.ActivityVisitEnum = Company.Account is "" or "NY" ? "new" : "recall";
|
||||
}
|
||||
|
||||
// Populate base activity information
|
||||
Activity.BcId = Company.BcId;
|
||||
Activity.ActivityStatusEnum = "noSale";
|
||||
Activity.VisitTypeEnum = Company.Account is "" or "NY" ? "new" : "recall";
|
||||
Activity.CompanyId = Company.CompanyId;
|
||||
Activity.SalesRepId = SalesRep.UserId;
|
||||
Activity.SalesRep = SalesRep.SalesRep;
|
||||
|
@ -169,7 +182,9 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
if (DraftProvider.Draft.DraftType == "order")
|
||||
{
|
||||
// set dropdown selection accordingly
|
||||
if(Activity.ActivityTypeEnum != "phone")
|
||||
Activity.ActivityTypeEnum = "onSite";
|
||||
|
||||
Activity.ActivityStatusEnum = "order";
|
||||
PoFormInvalid = false;
|
||||
}
|
||||
|
@ -177,91 +192,50 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
Working = false;
|
||||
}
|
||||
|
||||
|
||||
// #############################################################
|
||||
// overlays
|
||||
private async Task ShowVisitOverlay()
|
||||
{
|
||||
Logger.LogDebug("ShowInventoryOverlay - wait for visits");
|
||||
|
||||
ActivityListOverlay.Show();
|
||||
|
||||
Activities = await ActivityRepo.GetCustomerActivities(CompanyId);
|
||||
|
||||
await Task.Delay(500);
|
||||
}
|
||||
|
||||
|
||||
private async Task ShowInventoryOverlay()
|
||||
{
|
||||
Logger.LogDebug("ShowInventoryOverlay - wait for inventory");
|
||||
|
||||
InventoryListOverlay.Show();
|
||||
|
||||
Inventory = await HistoryRepo.FetchInventory(CompanyId);
|
||||
Inventory = Inventory.OrderBy(x => x.Description).ToList();
|
||||
await Task.Delay(500);
|
||||
}
|
||||
|
||||
private async Task OnInventoryCallback(DraftItem item)
|
||||
{
|
||||
Activity.ActivityStatusEnum = "order";
|
||||
DraftProvider.Draft.DraftType = "order";
|
||||
DraftProvider.Draft.Items.Add(item);
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task ShowInvoiceOverlay()
|
||||
{
|
||||
Logger.LogDebug("ShowInvoiceOverlay - wait for invoices");
|
||||
|
||||
InvoiceListOverlay.Show();
|
||||
CompanyInvoices = await FetchCompanyInvoices();
|
||||
await Task.Delay(500);
|
||||
}
|
||||
|
||||
private async Task<InvoiceListView> FetchCompanyInvoices()
|
||||
{
|
||||
// fetch from storage
|
||||
var storage = await Storage.GetItemAsStringAsync($"{CompanyId}-invoices");
|
||||
await Task.Delay(500);
|
||||
var iDate = await Storage.GetItemAsStringAsync($"{CompanyId}-iDate");
|
||||
|
||||
// if we have a list and iDate was today return the list
|
||||
if (!string.IsNullOrWhiteSpace(storage) && (!string.IsNullOrWhiteSpace(iDate) &&
|
||||
DateTime.Parse(iDate.Replace("\"", "")) >= DateTime.Now))
|
||||
private void ShowPriceListOverlay()
|
||||
{
|
||||
Logger.LogDebug("fetching invoices from storage");
|
||||
Logger.LogDebug("storage contains <= {}", storage);
|
||||
return JsonSerializer.Deserialize<InvoiceListView>(storage);
|
||||
CatalogOverlay.Show();
|
||||
}
|
||||
|
||||
Logger.LogDebug("pulling invoices from backend");
|
||||
// pull invoices
|
||||
var companyInvoices = await HistoryRepo.FetchInvoiceList(CompanyId);
|
||||
// send invoices to storage
|
||||
await Storage.SetItemAsync($"{CompanyId}-invoices", companyInvoices);
|
||||
await Storage.SetItemAsync($"{CompanyId}-iDate", $"{DateTime.Now:yyyy-MM-dd}");
|
||||
Logger.LogDebug(" --> return invoices from backend");
|
||||
Working = false;
|
||||
Logger.LogDebug("backend contains <= {}", JsonSerializer.Serialize(companyInvoices));
|
||||
return companyInvoices;
|
||||
}
|
||||
|
||||
private void ShowOrgWarning()
|
||||
{
|
||||
if (OrgWarning)
|
||||
return;
|
||||
OrgWarning = true;
|
||||
if (Company.CountryCode.ToLower() == "se" && Utils.StringToDigits(Activity.VatNumber).Length < 10 &&
|
||||
Activity.ActivityStatusEnum == "order")
|
||||
{
|
||||
Toaster.ShowWarning("Org nummer er ufuldstændig. Skal opdateres før bestilling kan sendes. ", "ADVARSEL");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CallConfirmCheckOverlay()
|
||||
{
|
||||
// check if new account
|
||||
if (string.IsNullOrWhiteSpace(Company.Account)
|
||||
|| Company.Account.ToLower() == "ny"
|
||||
|| Activity.ActivityStatusEnum.ToLower() == "quote")
|
||||
|| Activity.ActivityStatusEnum.ToLower() == "quote"
|
||||
|| Activity.ActivityStatusEnum.ToLower() == "canvas")
|
||||
{
|
||||
// proceed to create activity - as there is no product check to be done
|
||||
await CreateActivity();
|
||||
|
@ -316,38 +290,16 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
ConfirmationCheckOverlay.Show();
|
||||
}
|
||||
|
||||
private async Task ConfirmProductCheckCallback()
|
||||
|
||||
private void ShowPriceHistoryOverlay()
|
||||
{
|
||||
ConfirmationCheckOverlay.Hide();
|
||||
await CreateActivity();
|
||||
foreach (var item in CheckList)
|
||||
{
|
||||
item.Check = false;
|
||||
if (ShowItem)
|
||||
PriceOverlay.Show();
|
||||
}
|
||||
|
||||
await Storage.SetItemAsync($"{CompanyId}-products", CheckList);
|
||||
}
|
||||
|
||||
private async Task WorkDateConfirmCallback()
|
||||
{
|
||||
await PreferenceService.SetDateConfirmed(true);
|
||||
Activity.ActivityDate = $"{SelectedDate:yyyy-MM-dd}";
|
||||
ConfirmWorkDate.Hide();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task WorkDateComponentCallback(string workDate)
|
||||
{
|
||||
ReportClosed = await ReportRepo.ReportExist(workDate);
|
||||
SelectedDate = DateTime.Parse(workDate);
|
||||
Activity.ActivityDate = workDate;
|
||||
}
|
||||
|
||||
private void ShowPriceListOverlay()
|
||||
{
|
||||
CatalogOverlay.Show();
|
||||
}
|
||||
|
||||
// #############################################################
|
||||
// callbacks
|
||||
private async Task PriceListCallback(SelectedSku sku)
|
||||
{
|
||||
// get selected item
|
||||
|
@ -360,11 +312,6 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void ShowPriceHistoryOverlay()
|
||||
{
|
||||
if (ShowItem)
|
||||
PriceOverlay.Show();
|
||||
}
|
||||
|
||||
private void PriceHistoryCallback(decimal price)
|
||||
{
|
||||
|
@ -374,24 +321,97 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
StateHasChanged();
|
||||
}
|
||||
|
||||
|
||||
private void OnInventoryCallback(DraftItem item)
|
||||
{
|
||||
Activity.ActivityStatusEnum = "order";
|
||||
DraftProvider.Draft.DraftType = "order";
|
||||
DraftProvider.Draft.Items.Add(item);
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
|
||||
private async Task ConfirmProductCheckCallback()
|
||||
{
|
||||
ConfirmationCheckOverlay.Hide();
|
||||
await CreateActivity();
|
||||
foreach (var item in CheckList)
|
||||
{
|
||||
item.Check = false;
|
||||
}
|
||||
|
||||
await Storage.SetItemAsync($"{CompanyId}-products", CheckList);
|
||||
}
|
||||
|
||||
|
||||
private async Task WorkDateConfirmCallback()
|
||||
{
|
||||
await PreferenceService.SetDateConfirmed(true);
|
||||
Activity.ActivityDate = $"{SelectedDate:yyyy-MM-dd}";
|
||||
ConfirmWorkDate.Hide();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
|
||||
private async Task WorkDateComponentCallback(string workDate)
|
||||
{
|
||||
ReportClosed = await ReportRepo.ReportExist(workDate);
|
||||
SelectedDate = DateTime.Parse(workDate);
|
||||
Activity.ActivityDate = workDate;
|
||||
}
|
||||
|
||||
|
||||
// ################################################################################################
|
||||
// fetch invoices for customer
|
||||
private async Task<InvoiceListView> FetchCompanyInvoices()
|
||||
{
|
||||
// no need to do for kanvas entry
|
||||
if (Kanvas) return new InvoiceListView();
|
||||
// fetch from storage
|
||||
var storage = await Storage.GetItemAsStringAsync($"{CompanyId}-invoices");
|
||||
await Task.Delay(500);
|
||||
var iDate = await Storage.GetItemAsStringAsync($"{CompanyId}-iDate");
|
||||
// if we have a list and iDate was today return the list
|
||||
if (!string.IsNullOrWhiteSpace(storage) && (!string.IsNullOrWhiteSpace(iDate) &&
|
||||
DateTime.Parse(iDate.Replace("\"", "")) >= DateTime.Now))
|
||||
{
|
||||
Logger.LogDebug("fetching invoices from storage");
|
||||
Logger.LogDebug("storage contains <= {}", storage);
|
||||
return JsonSerializer.Deserialize<InvoiceListView>(storage);
|
||||
}
|
||||
Logger.LogDebug("pulling invoices from backend");
|
||||
// pull invoices
|
||||
var companyInvoices = await HistoryRepo.FetchInvoiceList(CompanyId);
|
||||
// send invoices to storage
|
||||
await Storage.SetItemAsync($"{CompanyId}-invoices", companyInvoices);
|
||||
await Storage.SetItemAsync($"{CompanyId}-iDate", $"{DateTime.Now:yyyy-MM-dd}");
|
||||
Logger.LogDebug(" --> return invoices from backend");
|
||||
Working = false;
|
||||
Logger.LogDebug("backend contains <= {}", JsonSerializer.Serialize(companyInvoices));
|
||||
return companyInvoices;
|
||||
}
|
||||
|
||||
|
||||
// ##################################################################################################
|
||||
// create activity
|
||||
private async Task CreateActivity()
|
||||
{
|
||||
// avoid duplication
|
||||
if (Working)
|
||||
return;
|
||||
|
||||
Logger.LogDebug("view kanvas activity => {}", JsonSerializer.Serialize(Activity));
|
||||
switch (Kanvas)
|
||||
{
|
||||
// validate customer address1
|
||||
// - this is a required input
|
||||
if (string.IsNullOrWhiteSpace(Activity.Address1))
|
||||
{
|
||||
case false when string.IsNullOrWhiteSpace(Activity.Address1):
|
||||
Toaster.ShowError("Kunde adresse er ufuldstændig.");
|
||||
return;
|
||||
}
|
||||
|
||||
// validate org number
|
||||
// - this is a required input
|
||||
// - must validate according to country rules.
|
||||
if (!VatUtils.ValidateFormat(Company.CountryCode, Activity.VatNumber))
|
||||
{
|
||||
case false when !VatUtils.ValidateFormat(Company.CountryCode, Activity.VatNumber):
|
||||
Toaster.ShowError("Firma registreringsnummer er ikke korrekt.");
|
||||
return;
|
||||
}
|
||||
|
@ -419,7 +439,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
// reset selected item
|
||||
SelectedItem = new SalesItemView();
|
||||
// check if phone number need to be updated
|
||||
if (OldPhone != Activity.Phone)
|
||||
if (!Kanvas && OldPhone != Activity.Phone)
|
||||
{
|
||||
Company.Phone = Activity.Phone;
|
||||
Activity.OrderMessage = $"BEMÆRK: {Activity.Phone}\n{Activity.OrderMessage}";
|
||||
|
@ -482,12 +502,29 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
Toaster.ShowError(result.Message, "ORDRE FEJL");
|
||||
}
|
||||
|
||||
|
||||
private void ShowOrgWarning()
|
||||
{
|
||||
if (Kanvas) return;
|
||||
if (OrgWarning) return;
|
||||
OrgWarning = true;
|
||||
if (Company.CountryCode.ToLower() == "se" && Utils.StringToDigits(Activity.VatNumber).Length < 10 &&
|
||||
Activity.ActivityStatusEnum == "order")
|
||||
{
|
||||
Toaster.ShowWarning("Org nummer er ufuldstændig. Skal opdateres før bestilling kan sendes. ", "ADVARSEL");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ###############################################################################
|
||||
// draft functions
|
||||
private async Task DeleteDraft()
|
||||
{
|
||||
await DraftProvider.DeleteDraftAsync();
|
||||
Activity.ActivityStatusEnum = "noSale";
|
||||
}
|
||||
|
||||
|
||||
private async Task AddItem(SalesItemView salesItem)
|
||||
{
|
||||
ShowItem = false;
|
||||
|
@ -513,6 +550,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
await DraftProvider.SaveChangesAsync();
|
||||
}
|
||||
|
||||
|
||||
private async Task RemoveItem(DraftItem item)
|
||||
{
|
||||
// remove item
|
||||
|
@ -523,6 +561,9 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
Activity.ActivityStatusEnum = "noSale";
|
||||
}
|
||||
|
||||
|
||||
// ##################################################################################################
|
||||
// form validation
|
||||
private void HandleFieldChanged(object sender, FieldChangedEventArgs e)
|
||||
{
|
||||
Logger.LogDebug("ActivityNewPage => HandleFieldChanged => ActivityStatusEnum <= '{}'",
|
||||
|
@ -556,6 +597,7 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
StateHasChanged();
|
||||
}
|
||||
|
||||
|
||||
private void ValidationChanged(object sender, ValidationStateChangedEventArgs e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Activity.ActivityTypeEnum) && !ReportClosed)
|
||||
|
@ -582,6 +624,9 @@ public partial class AdvisorActivityCreatePage : IDisposable
|
|||
ActivityContext.OnValidationStateChanged += ValidationChanged;
|
||||
}
|
||||
|
||||
|
||||
// #########################################################################################################
|
||||
// dispose
|
||||
public void Dispose()
|
||||
{
|
||||
Interceptor.DisposeEvent();
|
||||
|
|
|
@ -29,7 +29,9 @@
|
|||
</div>
|
||||
}
|
||||
<div class="row pt-2 mb-2 rounded rounded-2 bg-dark text-white">
|
||||
<h3>@Company.Name @(string.IsNullOrWhiteSpace(Company.Account) ? "" : "- ")@Company.Account</h3>
|
||||
<div class="col-sm-12">
|
||||
<span class="h3">@Company.Name</span> <span>(@Company.Account)</span>
|
||||
</div>
|
||||
</div>
|
||||
// erp context
|
||||
<EditForm EditContext="ErpContext">
|
||||
|
@ -89,15 +91,20 @@
|
|||
<InputText id="email" class="form-control" @bind-Value="Company.Email" readonly="@(ErpEditDisabled)"/>
|
||||
<ValidationMessage For="@(() => Company.Email)"></ValidationMessage>
|
||||
</div>
|
||||
|
||||
@if (!Kanvas)
|
||||
{
|
||||
<div class="col-sm-4">@* ---- placeholder --- *@</div>
|
||||
@* Force enable visit *@
|
||||
<div class="col-sm-3 d-grid mx-auto">
|
||||
<button type="button" class="btn btn-primary d-block" disabled="@(Company.HasFolded == 0 || Company.Name == "ERROR")" @onclick="ForceActivity">Aktiver besøg</button>
|
||||
</div>
|
||||
|
||||
@* Enable edit/save *@
|
||||
<div class="col-sm-2 d-grid mx-auto">
|
||||
<button type="button" class="btn btn-edit" @onclick="ToggleErpEdit"><i class="bi-pencil"></i> STAM data</button>
|
||||
</div>
|
||||
@* Force enable visit *@
|
||||
<div class="col-sm-3 d-grid mx-auto">
|
||||
<button type="button" class="btn btn-primary d-block" @onclick="ForceActivity">Aktiver besøg</button>
|
||||
</div>
|
||||
@* Save erp data *@
|
||||
<div class="col-sm-3 d-grid mx-auto">
|
||||
<button type="button" class="btn btn-danger d-block" onclick="@UpdateErpData" disabled="@(Working || Company.Name == "ERROR" || ErpEditDisabled)"><i class="bi-cloud-arrow-up"></i> STAM data </button>
|
||||
</div>
|
||||
|
@ -112,12 +119,16 @@
|
|||
<ValidationMessage For="@(() => Company.VatNumber)"></ValidationMessage>
|
||||
</div>
|
||||
</div>
|
||||
@* Enable edit/save vatnumber *@
|
||||
<div class="col-sm-2 d-grid mx-auto">
|
||||
<button type="button" class="btn btn-edit" @onclick="ToggleVatEdit"><i class="bi-pencil"></i> Moms/Org Nr.</button>
|
||||
</div>
|
||||
@* vat lookup *@
|
||||
<div class="col-sm-3 d-grid mx-auto">
|
||||
@switch (CountryCode)
|
||||
{
|
||||
case "dk":
|
||||
<button type="button" class="btn btn-info" @onclick="OpenVatLookupModal"><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;
|
||||
case "no":
|
||||
<a class="btn btn-info" href="https://brreg.no/" target="_blank"><i class="bi-search"></i> brreg.no</a>
|
||||
|
@ -127,27 +138,34 @@
|
|||
break;
|
||||
}
|
||||
</div>
|
||||
@* Enable edit/save *@
|
||||
<div class="col-sm-2 d-grid mx-auto">
|
||||
<button type="button" class="btn btn-edit" @onclick="ToggleVatEdit"><i class="bi-pencil"></i> Moms/Org Nr.</button>
|
||||
</div>
|
||||
@* save vat number *@
|
||||
<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>
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
|
||||
<hr class="mb-3"/>
|
||||
@* activity buttons *@
|
||||
<div class="row mt-3 mb-3">
|
||||
<div class="col-sm-3">
|
||||
@if (!Kanvas)
|
||||
{
|
||||
<a class="btn btn-danger d-block" href="/advisor/customers/@Company.CompanyId/invoices">Faktura</a>
|
||||
}
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
@if (!Kanvas)
|
||||
{
|
||||
<a class="btn btn-warning d-block" href="/advisor/customers/@Company.CompanyId/activities">Tidl. Besøg</a>
|
||||
}
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
@if (!Kanvas)
|
||||
{
|
||||
<a class="btn btn-success d-block" href="/advisor/customers/@Company.CompanyId/h/i">Produkter</a>
|
||||
}
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<ActivityButton ActionLink="@ActionLink"
|
||||
|
@ -158,6 +176,8 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
@if (!Kanvas)
|
||||
{
|
||||
<hr class="mb-3"/>
|
||||
@* crm context - OBS note *@
|
||||
<div class="row mb-2">
|
||||
|
@ -246,16 +266,15 @@
|
|||
<button type="button" class="btn btn-danger" @onclick="ToggleVisibility">@ToggleButtonText</button>
|
||||
</div>
|
||||
</div>
|
||||
</EditForm>
|
||||
|
||||
|
||||
@*
|
||||
<div class="row mt-5">
|
||||
<div class="col-sm-3">
|
||||
<a class="btn btn-info" href="@($"/advisor/customers/{CompanyId}/workplaces")">Arbejdssteder</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
*@
|
||||
}
|
||||
</EditForm>
|
||||
}
|
||||
|
||||
@if (Working)
|
||||
|
|
|
@ -71,6 +71,7 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
private ContactModal ContactPopup { get; set; } = new();
|
||||
private UserManagerEditView UserInfo { get; set; } = new();
|
||||
private string ToggleButtonText { get; set; } = "";
|
||||
private bool Kanvas { get; set; }
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
|
@ -96,16 +97,24 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
|
||||
Company = await CustomerRepo.GetCompanyById(CompanyId);
|
||||
|
||||
if (Company.Account.StartsWith("KANVAS"))
|
||||
Kanvas = true;
|
||||
|
||||
// internal flag
|
||||
EnableActivity = Company.ValidVat;
|
||||
// override if canvas which has account property as empty string or "NY"
|
||||
if (Company.Account == "NY" || Company.Account.StartsWith("KANVAS") || string.IsNullOrWhiteSpace(Company.Account))
|
||||
EnableActivity = 1;
|
||||
// action link passed to activity button component
|
||||
ActionLink = $"/advisor/customers/{CompanyId}/activities/new"; // used when drawing visit button
|
||||
// only execute if the company a 'real' customer
|
||||
if (!Kanvas)
|
||||
{
|
||||
Logger.LogDebug("company => {}", JsonSerializer.Serialize(Company));
|
||||
// toggle view button text
|
||||
ToggleButtonText = Company.IsHidden == 0 ? "Udelad kunde i oversigt" : "Brug Normal Visning";
|
||||
CurrentVat = Company.VatNumber;
|
||||
Company.CountryCode = UserInfo.CountryCode.ToLower();
|
||||
// internal flag
|
||||
EnableActivity = Company.ValidVat;
|
||||
// override if canvas which has account property as empty string or "NY"
|
||||
if (Company.Account == "NY" || string.IsNullOrWhiteSpace(Company.Account))
|
||||
EnableActivity = 1;
|
||||
// visit interval init
|
||||
if (Company.Interval == 0)
|
||||
Company.Interval = 8;
|
||||
|
@ -120,8 +129,6 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
NextVisit = LastVisit.AddDays(Company.Interval * 7);
|
||||
// display urgency of next visit
|
||||
VisitState = Utils.GetVisitState($"{NextVisit:yyyy-MM-dd}");
|
||||
// action link passed to activity button component
|
||||
ActionLink = $"/advisor/customers/{CompanyId}/activities/new"; // used when drawing visit button
|
||||
// handle company out of business case
|
||||
if (Company.HasFolded == 1)
|
||||
{
|
||||
|
@ -145,11 +152,12 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
CompanyVatAddress = PrepareVatAddress(Company);
|
||||
|
||||
await FetchContacts(CompanyId);
|
||||
await Task.Delay(100);
|
||||
await RequestErpUpdate();
|
||||
}
|
||||
|
||||
// remove loading image
|
||||
Working = false;
|
||||
await Task.Delay(100);
|
||||
await RequestErpUpdate();
|
||||
}
|
||||
|
||||
private void ToggleErpEdit()
|
||||
|
@ -414,6 +422,7 @@ public partial class AdvisorCustomerViewEditPage : IDisposable
|
|||
/// <param name="e"></param>
|
||||
private void HandleFieldChanged(object? sender, FieldChangedEventArgs? e)
|
||||
{
|
||||
|
||||
NextVisit = LastVisit.AddDays(Company.Interval * 7);
|
||||
// avoid nesting if by assuming ValidVat is false
|
||||
ValidVat = false;
|
||||
|
|
|
@ -153,7 +153,7 @@ public partial class OfficeOrderCreatePage : IDisposable
|
|||
|
||||
// setting up activity properties
|
||||
Activity.ActivityStatusEnum = "noSale";
|
||||
Activity.VisitTypeEnum = "recall";
|
||||
Activity.ActivityVisitEnum = "recall";
|
||||
Activity.ActivityTypeEnum = "phone";
|
||||
Activity.ActivityStatusEnum = "order";
|
||||
Activity.OurRef = $"T:{UserInfo.FirstName}";
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"appInfo": {
|
||||
"name": "Wonky Online",
|
||||
"version": "0.131.0",
|
||||
"version": "0.132.1",
|
||||
"rc": true,
|
||||
"sandBox": false,
|
||||
"image": "grumpy-coder.png"
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"System": "Debug",
|
||||
"Default": "Information",
|
||||
"System": "Information",
|
||||
"Microsoft": "Information"
|
||||
},
|
||||
"Debug": {
|
||||
|
@ -19,7 +19,7 @@
|
|||
}
|
||||
},
|
||||
"apiConfig": {
|
||||
"baseUrl": "https://dev.innotec.dk",
|
||||
"baseUrl": "https://zeta.innotec.dk",
|
||||
"catalog": "api/v2/catalog/country",
|
||||
"crmCustomers": "api/v2/crm/companies",
|
||||
"crmInventoryExt": "history/inventory",
|
||||
|
|
|
@ -28,160 +28,196 @@ public class ActivityDto
|
|||
/// <summary>
|
||||
/// Sales representative identification
|
||||
/// </summary>
|
||||
[Required] public string SalesRep { get; set; } = "";
|
||||
[Required]
|
||||
public string SalesRep { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Sales representative entity Id
|
||||
/// </summary>
|
||||
[Required] public string SalesRepId { get; set; } = "";
|
||||
[Required]
|
||||
public string SalesRepId { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Company countryCode (ensure correct code when office create ordre)
|
||||
/// </summary>
|
||||
[Required] public string CountryCode { get; set; } = "";
|
||||
[Required]
|
||||
public string CountryCode { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Company entity Id
|
||||
/// </summary>
|
||||
[Required] public string CompanyId { get; set; } = "";
|
||||
[Required]
|
||||
public string CompanyId { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Business Central entity Id
|
||||
/// </summary>
|
||||
public string BcId { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Customer account
|
||||
/// </summary>
|
||||
public string Account { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// VAT number
|
||||
/// </summary>
|
||||
[MaxLength(20, ErrorMessage = "Du kan højst bruge 20 tegn")]
|
||||
public string VatNumber { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Customer name
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "Navn skal udfyldes")]
|
||||
[MaxLength(100, ErrorMessage = "Du kan højst bruge 100 tegn")]
|
||||
public string Name { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Customer address city name
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "Byanvn skal udfyldes")]
|
||||
[MaxLength(30, ErrorMessage = "Du kan højst bruge 30 tegn")]
|
||||
public string City { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Customer address postal code
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "Postnr. skal udfyldes")]
|
||||
[MaxLength(20, ErrorMessage = "Du kan højst bruge 20 tegn")]
|
||||
public string ZipCode { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Customer address line 1
|
||||
/// </summary>
|
||||
[MaxLength(100, ErrorMessage = "Du kan højst bruge 100 tegn")]
|
||||
public string Address1 { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Customer address line 2
|
||||
/// </summary>
|
||||
[MaxLength(50, ErrorMessage = "Du kan højst bruge 50 tegn")]
|
||||
public string Address2 { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Customer office phone
|
||||
/// </summary>
|
||||
[MaxLength(20, ErrorMessage = "Du kan højst bruge 20 tegn")]
|
||||
public string Phone { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Customer mobile phone
|
||||
/// </summary>
|
||||
[MaxLength(20, ErrorMessage = "Du kan højst bruge 20 tegn")]
|
||||
public string Mobile { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Customer office email
|
||||
/// </summary>
|
||||
[MaxLength(80, ErrorMessage = "Du kan højst bruge 80 tegn")]
|
||||
public string Email { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Customer attention description
|
||||
/// </summary>
|
||||
[MaxLength(100, ErrorMessage = "Du kan højst bruge 100 tegn")]
|
||||
public string Attention { get; set; } = "";
|
||||
// Form entries
|
||||
/// <summary>
|
||||
/// Activity type enum as string
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "Vælg aktivitetstype")]
|
||||
public string ActivityTypeEnum { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Flag express order
|
||||
/// </summary>
|
||||
public bool Express { get; set; }
|
||||
|
||||
// Form entries
|
||||
/// <summary>
|
||||
/// Activity status enum as string
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "Vælg status for besøg ")]
|
||||
public string ActivityStatusEnum { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Activity type enum as string
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "Vælg aktivitetstype")]
|
||||
public string ActivityTypeEnum { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Visit type enum as string
|
||||
/// </summary>
|
||||
public string VisitTypeEnum { get; set; } = "recall";
|
||||
public string ActivityVisitEnum { get; set; } = "recall";
|
||||
|
||||
/// <summary>
|
||||
/// Activity date
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "Dato skal angives")]
|
||||
public string ActivityDate { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Product demonstration
|
||||
/// </summary>
|
||||
[MaxLength(50, ErrorMessage = "Du kan højst bruge 50 tegn")]
|
||||
public string Demo { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Our reference - system generated
|
||||
/// </summary>
|
||||
[MaxLength(20, ErrorMessage = "Du kan højst bruge 20 tegn")]
|
||||
public string OurRef { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Customer reference number
|
||||
/// </summary>
|
||||
[MaxLength(20, ErrorMessage = "Du kan højst bruge 20 tegn")]
|
||||
public string ReferenceNumber { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Customer reference description
|
||||
/// </summary>
|
||||
[MaxLength(35, ErrorMessage = "Du kan højst bruge 35 tegn")]
|
||||
public string YourRef { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Processing note to office
|
||||
/// </summary>
|
||||
[MaxLength(255, ErrorMessage = "Du kan højst bruge 255 tegn")]
|
||||
public string OrderMessage { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// CRM note for future reference
|
||||
/// </summary>
|
||||
[MaxLength(255, ErrorMessage = "Du kan højst bruge 255 tegn")]
|
||||
public string CrmNote { get; set; } = "";
|
||||
|
||||
// Delivery address form entries
|
||||
/// <summary>
|
||||
/// Customer delivery name
|
||||
/// </summary>
|
||||
[MaxLength(100, ErrorMessage = "Du kan højst bruge 100 tegn")]
|
||||
public string DlvName { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Customer delivery address line 1
|
||||
/// </summary>
|
||||
[MaxLength(100, ErrorMessage = "Du kan højst bruge 100 tegn")]
|
||||
public string DlvAddress1 { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Customer delivery address line 2
|
||||
/// </summary>
|
||||
[MaxLength(50, ErrorMessage = "Du kan højst bruge 50 tegn")]
|
||||
public string DlvAddress2 { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Customer delivery postal code
|
||||
/// </summary>
|
||||
[MaxLength(20, ErrorMessage = "Du kan højst bruge 20 tegn")]
|
||||
public string DlvZipCode { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Customer delivery city name
|
||||
/// </summary>
|
||||
[MaxLength(30, ErrorMessage = "Du kan højst bruge 30 tegn")]
|
||||
public string DlvCity { get; set; } = "";
|
||||
|
||||
// Lines
|
||||
/// <summary>
|
||||
/// Order lines
|
||||
|
|
Loading…
Reference in a new issue