WIP: evaluation and management

This commit is contained in:
Frede Hundewadt 2023-04-25 11:30:59 +02:00
parent 8f5178ae6d
commit 97cf9b8658
45 changed files with 683 additions and 614 deletions

View file

@ -42,7 +42,7 @@ public partial class OfficeCountryCustomerListComponent
// ******************************************************
// injects
[Inject] public ICountryCustomerHistoryRepository HistoryRepo { get; set; }
[Inject] public ICountryActivityRepository ActivityRepo { get; set; }
[Inject] public ICountryCustomerActivityRepository CustomerActivityRepo { get; set; }
// ******************************************************
// overlays
@ -67,7 +67,7 @@ public partial class OfficeCountryCustomerListComponent
// call erp to crm sync before requesting invoices
var newSyncDate = await HistoryRepo.RequestErpToCrmSync(CountryCode, companyId, SelectedCompany.HistorySync);
await Task.Delay(500);
InvoiceList = await HistoryRepo.RequestInvoiceList(CountryCode, companyId);
InvoiceList = await HistoryRepo.GetInvoiceList(CountryCode, companyId);
if(!string.IsNullOrWhiteSpace(newSyncDate)) SelectedCompany.HistorySync = newSyncDate;
InvoiceListOverlay.Show();
}
@ -77,7 +77,7 @@ public partial class OfficeCountryCustomerListComponent
// check for console manipulation
if (!Utils.Validate(ValidateType.Id, companyId)) return;
SelectedCompany = CompanyList.First(x => x.CompanyId == companyId);
ActivityList = await ActivityRepo.RequestActivityList(companyId);
ActivityList = await CustomerActivityRepo.GetActivityList(companyId);
ActivityListOverlay.Show();
}
@ -90,7 +90,7 @@ public partial class OfficeCountryCustomerListComponent
var newSyncDate = await HistoryRepo.RequestErpToCrmSync(CountryCode, companyId, SelectedCompany.HistorySync);
await Task.Delay(500);
if(!string.IsNullOrWhiteSpace(newSyncDate)) SelectedCompany.HistorySync = newSyncDate;
ProductList = await HistoryRepo.RequestInventory(SelectedCompany.CountryCode, SelectedCompany.CompanyId);
ProductList = await HistoryRepo.GetInventory(SelectedCompany.CountryCode, SelectedCompany.CompanyId);
ProductListOverlay.Show();
}

View file

@ -39,7 +39,7 @@ public static class Utils
new (){ Name = "Advisor", Assigned = model.Advisor},
new (){ Name = "EDoc", Assigned = model.EDoc},
new (){ Name = "EShop", Assigned = model.EShop},
new (){ Name = "Managment", Assigned = model.Management},
new (){ Name = "Management", Assigned = model.Management},
new (){ Name = "Office", Assigned = model.Office},
new (){ Name = "Supervisor", Assigned = model.Supervisor},
new (){ Name = "Warehouse", Assigned = model.Warehouse}

View file

@ -58,9 +58,11 @@ public class AdvisorActivityRepository : IAdvisorActivityRepository
if (!result.IsSuccessStatusCode)
return new List<ReportItemView>();
var content = await result.Content.ReadAsStringAsync();
return string.IsNullOrWhiteSpace(content)
? new List<ReportItemView>()
: JsonSerializer.Deserialize<List<ReportItemView>>(content, _options);
if (string.IsNullOrWhiteSpace(content))
{
return new List<ReportItemView>();
}
return JsonSerializer.Deserialize<List<ReportItemView>>(content, _options) ?? new List<ReportItemView>();
}
/// <summary>
@ -70,11 +72,22 @@ public class AdvisorActivityRepository : IAdvisorActivityRepository
/// <returns></returns>
public async Task<ApiResponseView> UpdateQuoteStatus(ReportItemView activity)
{
var resp = new ApiResponseView
{
Code = 404,
IsSuccess = false,
Message = "",
Id = ""
};
var response = await _client.PutAsJsonAsync(
$"{_api.CrmActivities}/quote/{activity.ActivityId}", activity, _options);
var content = await response.Content.ReadAsStringAsync();
if (string.IsNullOrWhiteSpace(content))
{
return resp;
}
_logger.LogDebug("UpdateQuote Response Content <= {}", content);
return JsonSerializer.Deserialize<ApiResponseView>(content, _options);
return JsonSerializer.Deserialize<ApiResponseView>(content, _options) ?? resp;
}
/// <summary>

View file

@ -23,9 +23,6 @@ using Wonky.Entity.Views;
namespace Wonky.Client.HttpRepository;
/// <summary>
/// Implementing Interface Activity CRM Http repository
/// </summary>
public class CountryActivityRepository : ICountryActivityRepository
{
private readonly JsonSerializerOptions? _options = new JsonSerializerOptions
@ -38,6 +35,7 @@ public class CountryActivityRepository : ICountryActivityRepository
private readonly HttpClient _client;
private readonly ApiConfig _api;
public CountryActivityRepository(HttpClient client,
ILogger<CountryActivityRepository> logger,
NavigationManager navigation, IOptions<ApiConfig> configuration)
@ -48,40 +46,27 @@ public class CountryActivityRepository : ICountryActivityRepository
_api = configuration.Value;
}
/// <summary>
/// Get activity data by id
/// </summary>
/// <param name="activityId"></param>
/// <returns></returns>
public async Task<ActivityDto> RequestActivity(string activityId)
public async Task<ReportItemView> GetActivity(string activityId)
{
var activity = await _client
.GetFromJsonAsync<ActivityDto>($"{_api.CrmActivities}/{activityId}");
return activity ?? new ActivityDto();
.GetFromJsonAsync<ReportItemView>($"{_api.OfficeActivities}/id/{activityId}");
return activity ?? new ReportItemView();
}
/// <summary>
/// Get activities for customer Id
/// </summary>
/// <param name="customerId"></param>
/// <returns></returns>
public async Task<List<ReportItemView>> RequestActivityList(string customerId)
public async Task<List<ReportItemView>> GetActivityList(string companyId)
{
var response = await _client.GetAsync($"{_api.CrmActivities}/company/{customerId}");
var response = await _client.GetAsync($"{_api.OfficeActivities}/company/{companyId}");
var content = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
if (!response.IsSuccessStatusCode || string.IsNullOrWhiteSpace(content))
{
return new List<ReportItemView>();
return string.IsNullOrWhiteSpace(content)
? new List<ReportItemView>()
: JsonSerializer.Deserialize<List<ReportItemView>>(content, _options);
}
public async Task<ApiResponseView> CreatePhoneOrder(string customerId, ActivityDto activity)
{
var response = await _client.PostAsJsonAsync($"{_api.OfficeCustomers}/{activity.CountryCode}/id/{customerId}/activities", activity);
var content = await response.Content.ReadAsStringAsync();
return string.IsNullOrWhiteSpace(content)
? new ApiResponseView { Code = 0, Id = "", IsSuccess = false, Message = "Ukendt fejl er opstået." }
: JsonSerializer.Deserialize<ApiResponseView>(content, _options);
}
return JsonSerializer.Deserialize<List<ReportItemView>>(content, _options) ?? new List<ReportItemView>();
}
}

View file

@ -0,0 +1,86 @@
// Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using System.Net.Http.Json;
using System.Text.Json;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Options;
using Wonky.Entity.Configuration;
using Wonky.Entity.DTO;
using Wonky.Entity.Views;
namespace Wonky.Client.HttpRepository;
public class CountryCustomerActivityRepository : ICountryCustomerActivityRepository
{
private readonly JsonSerializerOptions? _options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
private readonly NavigationManager _navigation;
private readonly ILogger<CountryCustomerActivityRepository> _logger;
private readonly HttpClient _client;
private readonly ApiConfig _api;
public CountryCustomerActivityRepository(HttpClient client,
ILogger<CountryCustomerActivityRepository> logger,
NavigationManager navigation, IOptions<ApiConfig> configuration)
{
_client = client;
_logger = logger;
_navigation = navigation;
_api = configuration.Value;
}
public async Task<ActivityDto> GetActivity(string activityId)
{
var activity = await _client
.GetFromJsonAsync<ActivityDto>($"{_api.CrmActivities}/{activityId}");
return activity ?? new ActivityDto();
}
public async Task<List<ReportItemView>> GetActivityList(string customerId)
{
var response = await _client.GetAsync($"{_api.CrmActivities}/company/{customerId}");
var content = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode || string.IsNullOrWhiteSpace(content))
{
return new List<ReportItemView>();
}
return JsonSerializer.Deserialize<List<ReportItemView>>(content, _options) ?? new List<ReportItemView>();
}
public async Task<ApiResponseView> PostPhoneOrder(string customerId, ActivityDto activity)
{
var respView = new ApiResponseView
{ Code = 0, Id = "", IsSuccess = false, Message = "Ukendt fejl er opstået." };
var response = await _client.PostAsJsonAsync($"{_api.OfficeCustomers}/{activity.CountryCode}/id/{customerId}/activities", activity);
var content = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode || string.IsNullOrWhiteSpace(content))
{
return respView;
}
return JsonSerializer.Deserialize<ApiResponseView>(content, _options) ?? respView;
}
}

View file

@ -44,109 +44,104 @@ public class CountryCustomerHistoryRepository : ICountryCustomerHistoryRepositor
_api = configuration.Value;
}
/// <summary>
/// Fetch Invoice LIst
/// </summary>
/// <param name="countryCode"></param>
/// <param name="companyId"></param>
/// <returns></returns>
public async Task<InvoiceListView> RequestInvoiceList(string countryCode, string companyId)
public async Task<InvoiceListView> GetInvoiceList(string countryCode, string companyId)
{
var response = await _client.GetAsync($"{_api.OfficeCustomers}/{countryCode}/{companyId}/invoices");
if (!response.IsSuccessStatusCode) return new InvoiceListView();
var response = await _client
.GetAsync($"{_api.OfficeCustomers}/{countryCode}/{companyId}/invoices");
var content = await response.Content.ReadAsStringAsync();
return response.IsSuccessStatusCode
? JsonSerializer.Deserialize<InvoiceListView>(content, _options)
: new InvoiceListView();
if (!response.IsSuccessStatusCode || string.IsNullOrWhiteSpace(content))
{
return new InvoiceListView();
}
return JsonSerializer.Deserialize<InvoiceListView>(content, _options)
?? new InvoiceListView();
}
/// <summary>
/// Fetch given invoice for given customer
/// </summary>
/// <param name="countryCode"></param>
/// <param name="companyId"></param>
/// <param name="invoiceId"></param>
/// <returns></returns>
public async Task<InvoiceView> FetchInvoice(string countryCode, string companyId, string invoiceId)
public async Task<InvoiceView> GetInvoice(string countryCode, string companyId, string invoiceId)
{
var response = await _client
.GetAsync($"{_api.OfficeCustomers}/{countryCode}/{companyId}/invoices/{invoiceId}");
if (!response.IsSuccessStatusCode) return new InvoiceView();
var content = await response.Content.ReadAsStringAsync();
return response.IsSuccessStatusCode
? JsonSerializer.Deserialize<InvoiceView>(content, _options)
: new InvoiceView();
if (!response.IsSuccessStatusCode || string.IsNullOrWhiteSpace(content))
{
return new InvoiceView();
}
return JsonSerializer.Deserialize<InvoiceView>(content, _options)
?? new InvoiceView();
}
/// <summary>
/// Fetch inventory from given customer
/// </summary>
/// <param name="countryCode"></param>
/// <param name="companyId"></param>
/// <returns></returns>
public async Task<List<ProductInventoryView>> RequestInventory(string countryCode, string companyId)
public async Task<List<ProductInventoryView>> GetInventory(string countryCode, string companyId)
{
var response = await _client.GetAsync($"{_api.OfficeCustomers}/{countryCode}/{companyId}/history/inventory");
if (!response.IsSuccessStatusCode)
var response = await _client
.GetAsync($"{_api.OfficeCustomers}/{countryCode}/{companyId}/history/inventory");
var content = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode || string.IsNullOrWhiteSpace(content))
{
return new List<ProductInventoryView>();
var content = await response.Content.ReadAsStringAsync();
return string.IsNullOrWhiteSpace(content)
? new List<ProductInventoryView>()
: JsonSerializer.Deserialize<List<ProductInventoryView>>(content, _options);
}
return JsonSerializer.Deserialize<List<ProductInventoryView>>(content, _options)
?? new List<ProductInventoryView>();
}
/// <summary>
/// Fetch History for given customer
/// </summary>
/// <param name="countryCode"></param>
/// <param name="companyId"></param>
/// <returns></returns>
public async Task<List<ProductHistoryView>> FetchHistory(string countryCode, string companyId)
public async Task<List<ProductHistoryView>> GetHistory(string countryCode, string companyId)
{
var response = await _client.GetAsync($"{_api.OfficeCustomers}/{countryCode}/{companyId}/history/products");
if (!response.IsSuccessStatusCode) return new List<ProductHistoryView>();
var response = await _client
.GetAsync($"{_api.OfficeCustomers}/{countryCode}/{companyId}/history/products");
var content = await response.Content.ReadAsStringAsync();
return string.IsNullOrWhiteSpace(content)
? new List<ProductHistoryView>()
: JsonSerializer.Deserialize<List<ProductHistoryView>>(content, _options);
}
/// <summary>
/// Fetch history for given customer and a given product
/// </summary>
/// <param name="countryCode"></param>
/// <param name="companyId"></param>
/// <param name="sku"></param>
/// <returns></returns>
public async Task<List<ProductHistoryView>> FetchHistorySku(string countryCode, string companyId, string sku)
{
var response = await _client.GetAsync($"{_api.OfficeCustomers}/{countryCode}/{companyId}/history/products/{sku}");
if (!response.IsSuccessStatusCode)
if (!response.IsSuccessStatusCode || string.IsNullOrWhiteSpace(content))
{
return new List<ProductHistoryView>();
var content = await response.Content.ReadAsStringAsync();
return string.IsNullOrWhiteSpace(content)
? new List<ProductHistoryView>()
: JsonSerializer.Deserialize<List<ProductHistoryView>>(content, _options);
}
return JsonSerializer.Deserialize<List<ProductHistoryView>>(content, _options)
?? new List<ProductHistoryView>();
}
/// <summary>
/// RPC call to initiate remote server sync for given customer
/// </summary>
/// <param name="countryCode"></param>
/// <param name="companyId"></param>
/// <param name="syncDate"></param>
/// <returns></returns>
public async Task<List<ProductHistoryView>> GetSkuHistory(string countryCode, string companyId, string sku)
{
var response = await _client
.GetAsync($"{_api.OfficeCustomers}/{countryCode}/{companyId}/history/products/{sku}");
var content = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode || string.IsNullOrWhiteSpace(content))
{
return new List<ProductHistoryView>();
}
return JsonSerializer.Deserialize<List<ProductHistoryView>>(content, _options)
?? new List<ProductHistoryView>();
}
public async Task<string> RequestErpToCrmSync(string countryCode, string companyId, string syncDate)
{
var x = await _client.GetAsync($"{_api.OfficeCustomers}/{countryCode}/{companyId}/{_api.SyncRpcInvoiceExt}/{syncDate}");
if (!x.IsSuccessStatusCode)
var response = await _client
.GetAsync($"{_api.OfficeCustomers}/{countryCode}/{companyId}/{_api.SyncRpcInvoiceExt}/{syncDate}");
var content = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode || string.IsNullOrWhiteSpace(content))
{
return string.Empty;
var content = await x.Content.ReadAsStringAsync();
}
return content.Replace("\"", "");
}
}

View file

@ -22,7 +22,7 @@ using Wonky.Entity.Views;
namespace Wonky.Client.HttpRepository;
public class OfficeUserInfoRepository : IOfficeUserInfoRepository
public class CountryUserInfoRepository : ICountryUserInfoRepository
{
private readonly JsonSerializerOptions? _options = new JsonSerializerOptions
{
@ -30,11 +30,11 @@ public class OfficeUserInfoRepository : IOfficeUserInfoRepository
};
private readonly NavigationManager _navigation;
private ILogger<OfficeUserInfoRepository> _logger;
private ILogger<CountryUserInfoRepository> _logger;
private readonly HttpClient _client;
private readonly ApiConfig _api;
public OfficeUserInfoRepository(HttpClient client, ILogger<OfficeUserInfoRepository> logger,
public CountryUserInfoRepository(HttpClient client, ILogger<CountryUserInfoRepository> logger,
NavigationManager navigation, IOptions<ApiConfig> configuration)
{
_client = client;

View file

@ -34,7 +34,7 @@ public class EvaluationRepository : IEvaluationRepository
public async Task<ManagerView> GetManagerByUserId(string userId)
{
var result = await _client
.GetFromJsonAsync<ManagerView>($"{_api.MemberEvaluation}", _options);
.GetFromJsonAsync<ManagerView>($"{_api.MemberEvaluation}/id/manager/{userId}", _options);
return result ?? new ManagerView();
}
@ -43,13 +43,13 @@ public class EvaluationRepository : IEvaluationRepository
public async Task<MemberView> GetMemberByUserId(string userId)
{
var result = await _client
.GetFromJsonAsync<MemberView>($"{_api.MemberEvaluation}", _options);
.GetFromJsonAsync<MemberView>($"{_api.MemberEvaluation}/id/member/{userId}", _options);
return result ?? new MemberView();
}
public async Task<List<EvaluationEditView>> GetByManager(string managerId)
public async Task<List<EvaluationEditView>> GetEvaluationsByManagerId(string managerId)
{
var result = await _client
.GetFromJsonAsync<List<EvaluationEditView>>(
@ -59,7 +59,7 @@ public class EvaluationRepository : IEvaluationRepository
}
public async Task<List<EvaluationEditView>> GetByMember(string memberId)
public async Task<List<EvaluationEditView>> GetEvaluationsByMemberId(string memberId)
{
var result = await _client
.GetFromJsonAsync<List<EvaluationEditView>>(

View file

@ -18,24 +18,9 @@ using Wonky.Entity.Views;
namespace Wonky.Client.HttpRepository;
/// <summary>
/// Interface Activity CRM Http repository
/// </summary>
public interface ICountryActivityRepository
{
/// <summary>
/// Get activity data by id
/// </summary>
/// <param name="activityId"></param>
/// <returns></returns>
Task<ActivityDto> RequestActivity(string activityId);
/// <summary>
/// Get activities for customer Id
/// </summary>
/// <param name="customerId"></param>
/// <returns></returns>
Task<List<ReportItemView>> RequestActivityList(string customerId);
Task<ReportItemView> GetActivity(string activityId);
Task<ApiResponseView> CreatePhoneOrder(string customerId, ActivityDto activity);
Task<List<ReportItemView>> GetActivityList(string companyId);
}

View file

@ -0,0 +1,28 @@
// Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using Wonky.Entity.DTO;
using Wonky.Entity.Views;
namespace Wonky.Client.HttpRepository;
public interface ICountryCustomerActivityRepository
{
Task<ActivityDto> GetActivity(string activityId);
Task<List<ReportItemView>> GetActivityList(string customerId);
Task<ApiResponseView> PostPhoneOrder(string customerId, ActivityDto activity);
}

View file

@ -0,0 +1,33 @@
// Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using Wonky.Entity.Views;
namespace Wonky.Client.HttpRepository;
public interface ICountryCustomerHistoryRepository
{
Task<InvoiceListView> GetInvoiceList(string countryCode, string companyId);
Task<InvoiceView> GetInvoice(string countryCode, string companyId, string invoiceId);
Task<List<ProductInventoryView>> GetInventory(string countryCode, string companyId);
Task<List<ProductHistoryView>> GetHistory(string countryCode, string companyId);
Task<List<ProductHistoryView>> GetSkuHistory(string countryCode, string companyId, string sku);
Task<string> RequestErpToCrmSync(string countryCode, string companyId, string syncDate);
}

View file

@ -21,7 +21,7 @@ namespace Wonky.Client.HttpRepository;
/// <summary>
/// Interface for User handling over http
/// </summary>
public interface IOfficeUserInfoRepository
public interface ICountryUserInfoRepository
{
/// <summary>
/// Get Users

View file

@ -7,8 +7,8 @@ public interface IEvaluationRepository
{
Task<ManagerView> GetManagerByUserId(string userId);
Task<MemberView> GetMemberByUserId(string userId);
Task<List<EvaluationEditView>> GetByManager(string managerId);
Task<List<EvaluationEditView>> GetByMember(string memberId);
Task<List<EvaluationEditView>> GetEvaluationsByManagerId(string managerId);
Task<List<EvaluationEditView>> GetEvaluationsByMemberId(string memberId);
Task<EvaluationEditView> GetById(string evaluationId);
Task<EvaluationEditView> CreateEvaluation(EvaluationEditView evaluationEditView);
Task<EvaluationEditView> UpdateEvaluation(string evaluationId, EvaluationEditView evaluationEditView);

View file

@ -1,69 +0,0 @@
// Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using Wonky.Entity.Views;
namespace Wonky.Client.HttpRepository;
/// <summary>
/// Interface Customer History CRM Http repository
/// </summary>
public interface ICountryCustomerHistoryRepository
{
/// <summary>
/// Fetch Invoice LIst
/// </summary>
/// <param name="companyId"></param>
/// <returns></returns>
Task<InvoiceListView> RequestInvoiceList(string countryCode, string companyId);
/// <summary>
/// Fetch given invoice for given customer
/// </summary>
/// <param name="companyId"></param>
/// <param name="invoiceId"></param>
/// <returns></returns>
Task<InvoiceView> FetchInvoice(string countryCode, string companyId, string invoiceId);
/// <summary>
/// Fetch inventory from given customer
/// </summary>
/// <param name="companyId"></param>
/// <returns></returns>
Task<List<ProductInventoryView>> RequestInventory(string countryCode, string companyId);
/// <summary>
/// Fetch History for given customer
/// </summary>
/// <param name="companyId"></param>
/// <returns></returns>
Task<List<ProductHistoryView>> FetchHistory(string countryCode, string companyId);
/// <summary>
/// Fetch history for given customer and a given product
/// </summary>
/// <param name="companyId"></param>
/// <param name="sku"></param>
/// <returns></returns>
Task<List<ProductHistoryView>> FetchHistorySku(string countryCode, string companyId, string sku);
/// <summary>
/// RPC call to initiate remote server sync for given customer
/// </summary>
/// <param name="companyId"></param>
/// <param name="syncDate"></param>
/// <returns></returns>
Task<string> RequestErpToCrmSync(string countryCode, string companyId, string syncDate);
}

View file

@ -42,7 +42,7 @@ public partial class OfficeCustomerInventoryReorderOverlay
if (string.IsNullOrWhiteSpace(SalesItem.Sku))
return;
History = await HistoryRepo.FetchHistorySku(Company.CountryCode, Company.CompanyId, SalesItem.Sku);
History = await HistoryRepo.GetSkuHistory(Company.CountryCode, Company.CompanyId, SalesItem.Sku);
// if (!History.Any())
// await Task.Delay(500);
SelectedItem.Item = SalesItem;

View file

@ -41,7 +41,7 @@ public partial class OfficeCustomerInvoiceViewOverlay : IDisposable
if (!string.IsNullOrWhiteSpace(InvoiceId))
{
Invoice = await HistoryRepo.FetchInvoice( CountryCode, CompanyId, InvoiceId);
Invoice = await HistoryRepo.GetInvoice( CountryCode, CompanyId, InvoiceId);
}
}

View file

@ -42,7 +42,7 @@ public partial class OfficeOrderInventoryReorderOverlay
if (string.IsNullOrWhiteSpace(SalesItem.Sku))
return;
ProductHistory = await HistoryRepo.FetchHistorySku(Company.CountryCode, Company.CompanyId, SalesItem.Sku);
ProductHistory = await HistoryRepo.GetSkuHistory(Company.CountryCode, Company.CompanyId, SalesItem.Sku);
if (!ProductHistory.Any())
await Task.Delay(250);
SelectedItem.Item = SalesItem;

View file

@ -16,7 +16,7 @@
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Roles = "Management,Supervisor")]
@page "/management/members/{UserId}/evaluations"
@page "/supervisor/members/{UserId}/evaluations"
<PageTitle>Evalueringer</PageTitle>
@ -26,7 +26,7 @@
</div>
<div class="col">
<div class="text-end">
<a class="btn btn-primary" href="/management/members/@UserId/evaluations/new"><i class="bi-plus-circle-fill"></i> Opret Evaluering</a>
<a class="btn btn-primary" href="/supervisor/members/@UserId/evaluations/new"><i class="bi-plus-circle-fill"></i> Opret Evaluering</a>
@*
<div class="busy-signal" style="display:@(_working ? "block" : "none")">
<div class="spinner-grow text-info" role="status">

View file

@ -38,27 +38,23 @@ public partial class ManagerEvaluationListPage : IDisposable
private List<EvaluationEditView> Evaluations { get; set; } = new();
private MemberView Member { get; set; } = new();
private bool _working = true;
protected override async Task OnParametersSetAsync()
{
Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent();
Member = await EvaluationRepo.GetMemberByUserId(UserId);
while (string.IsNullOrWhiteSpace(Member.MemberId))
{
await Task.Delay(250);
}
Logger.LogDebug("Member => {}",JsonSerializer.Serialize(Member));
}
protected override async Task OnInitializedAsync()
{
Evaluations = await EvaluationRepo.GetByMember(Member.MemberId);
Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent();
Logger.LogDebug("{}",JsonSerializer.Serialize(Evaluations));
Logger.LogDebug("UserId => {}", UserId);
Member = await EvaluationRepo.GetMemberByUserId(UserId);
Logger.LogDebug("Member => {}",JsonSerializer.Serialize(Member));
Evaluations = await EvaluationRepo.GetEvaluationsByMemberId(Member.MemberId);
Logger.LogDebug("Evaluations => {}",JsonSerializer.Serialize(Evaluations));
_working = false;

View file

@ -17,7 +17,7 @@
@attribute [Authorize(Roles = "Management,Supervisor")]
@page "/management/members/{UserId}/evaluations/new"
@page "/supervisor/members/{UserId}/evaluations/new"
<PageTitle>Ny evaluering</PageTitle>

View file

@ -13,6 +13,7 @@
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using System.Text.Json;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Wonky.Client.HttpInterceptors;
@ -30,6 +31,8 @@ public partial class ManagerEvaluationNewPage : IDisposable
[Inject] public IEvaluationRepository EvaluationRepo { get; set; }
[Inject] public HttpInterceptorService Interceptor { get; set; }
[Inject] public IUserInfoService UserService { get; set; }
[Inject] public ILogger<ManagerEvaluationNewPage> Logger { get; set; }
// ############################################################
[Parameter] public string UserId { get; set; } = "";
@ -47,10 +50,16 @@ public partial class ManagerEvaluationNewPage : IDisposable
Interceptor.RegisterBeforeSendEvent();
Member = await EvaluationRepo.GetMemberByUserId(UserId);
Logger.LogDebug("Member => {}", JsonSerializer.Serialize(Member));
var managerId = await UserService.GetUserId();
Logger.LogDebug("ManagerId => {}", managerId);
Manager = await EvaluationRepo.GetManagerByUserId(managerId);
Logger.LogDebug("Manager => {}", JsonSerializer.Serialize(Manager));
}

View file

@ -17,7 +17,7 @@
@attribute [Authorize(Roles = "Management,Supervisor")]
@page "/management/members/{UserId}/evaluations/{EvaluationId}"
@page "/supervisor/members/{UserId}/evaluations/{EvaluationId}"
<div class="row">
<div class="col">

View file

@ -0,0 +1,48 @@
@* Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
*@
@using Wonky.Client.Components
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Roles = "Management,Supervisor")]
@page "/supervisor/members/{UserId}/activities/{ReportDate}"
<div class="report-main d-print-print">
@if (!string.IsNullOrWhiteSpace(Report.ReportData.DayTypeEnum))
{
<PageTitle>@Report.ReportData.Name</PageTitle>
<div class="row">
<div class="alert border border-1 border-dark text-center align-content-center">
<h3>@Report.ReportData.Name</h3>
</div>
</div>
<div class="row">
<div class="w-75">
<ReportViewSummaryComponent ReportData="Report.ReportData"/>
</div>
<div class="w-25">
<ReportViewDistanceLedgerComponent ReportData="Report.ReportData"/>
</div>
</div>
<ReportViewActivityListComponent ActivityList="Report.ReportItems" OnShowDocument="ShowDocument"/>
<ReportViewActivityLedgerComponent ReportData="Report.ReportData"/>
}
else
{
<div class="row">
<div class="col">Ingen rapport data</div>
</div>
}
</div>

View file

@ -0,0 +1,150 @@
// Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using System.Text.Json;
using Blazored.LocalStorage;
using Blazored.Toast.Services;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using Wonky.Client.Helpers;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpRepository;
using Wonky.Client.Local.Services;
using Wonky.Client.Models;
using Wonky.Entity.DTO;
using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Pages;
public partial class ManagerMemberActivityListViewPage : IDisposable
{
// #############################################################
[Inject] public HttpInterceptorService Interceptor { get; set; }
[Inject] public ICountryReportRepository ReportRepo { get; set; }
[Inject] public NavigationManager Navigator { get; set; }
[Inject] public ILogger<ManagerMemberActivityListViewPage> Logger { get; set; }
[Inject] public ILocalStorageService Storage { get; set; }
[Inject] public UserPreferenceService PreferenceService { get; set; }
[Inject] public IToastService Toaster { get; set; }
[Inject] public IOrderProcessRepository ProcessRepo { get; set; }
// [Inject] public EventCallback<string> OnShowDocument { get; set; }
// #############################################################
[Parameter] public string UserId { get; set; } = "";
[Parameter] public string ReportDate { get; set; } = "";
// #############################################################
private IJSObjectReference JsModule { get; set; }
private ReportView Report { get; set; } = new();
private List<ReportItemView> Activities { get; set; } = new();
private bool Working { get; set; } = true;
private UserPreference Profile { get; set; } = new();
private string _returnUrl = "";
protected override async Task OnParametersSetAsync()
{
Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent();
PreferenceService.OnChange += ProfileServiceOnOnChange;
await PreferenceService.SetWorkDate(DateTime.Parse(ReportDate));
await FetchUserReport(ReportDate);
}
/// <summary>
/// Event handler to show the document by Id
/// </summary>
/// <param name="documentId"></param>
private void ShowDocument(string documentId)
{
// shoe order/activity document
// the supervisor version
Navigator.NavigateTo($"/supervisor/members/{UserId}/activities/{ReportDate}/visits/{documentId}");
}
/// <summary>
/// Work date component event handler
/// </summary>
/// <param name="workDate"></param>
private async Task FetchUserReport(string workDate)
{
// remove busy signal if report is empty
if (string.IsNullOrWhiteSpace(Report.ReportData.ReportDate))
{
Working = false;
}
ReportDate = workDate;
// ensure the browser address bar contains the correct link
Navigator.NavigateTo($"/supervisor/members/{UserId}/activities/{workDate}", false, true);
// return if we are already at it
if (Working)
{
return;
}
// reset variables
Report = new ReportView();
Activities = new List<ReportItemView>();
// set busy signal
Working = true;
Logger.LogDebug("UserId => {}", UserId);
// fetch report
Report = await ReportRepo.GetCountryReport(UserId, workDate);
Logger.LogDebug("Report => {}", JsonSerializer.Serialize(Report, new JsonSerializerOptions(JsonSerializerDefaults.Web)));
// extract activities
Activities = Report.ReportItems.Where(x => x.Lines.Any()).ToList();
// store locally
if (!string.IsNullOrWhiteSpace(Report.ReportData.ReportDate))
{
await Storage.SetItemAsync($"{UserId}-{workDate}", Report);
}
// remove busy signal
Working = false;
}
private void ProfileServiceOnOnChange(UserPreference userPreference)
{
Logger.LogDebug("OfficeReportViewPage => ProfileServiceOnOnChange");
Profile = userPreference;
Logger.LogDebug("OfficeReportViewPage => ProfileServiceOnOnChange => Prefs.WorkDate <= {}", Profile.WorkDate);
ReportDate = Profile.WorkDate;
StateHasChanged();
}
public void Dispose()
{
Interceptor.DisposeEvent();
PreferenceService.OnChange -= ProfileServiceOnOnChange;
}
}

View file

@ -13,36 +13,145 @@
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
*@
@using Wonky.Client.Components
@using Microsoft.AspNetCore.Authorization
@using Wonky.Client.Components
@attribute [Authorize(Roles = "Management,Supervisor")]
@page "/management/members/{UserId}/activities/{ReportDate}"
@page "/supervisor/members/{UserId}/activities/{ReportDate}/visits/{DocumentId}"
<div class="report-main d-print-print">
@if (!string.IsNullOrWhiteSpace(Report.ReportData.DayTypeEnum))
<PageTitle>@ReportItem.ESalesNumber - @ReportItem.Company.Name</PageTitle>
<table class="table table-sm table-striped d-print-table">
<thead>
<tr>
<th class="p-0" colspan="4">
<div class="bg-light text-dark border border-1 rounded-3 pt-3 mb-2">
<h2 class="fw-bold text-center">@ReportItem.Company.Name</h2>
@if (ReportItem.Express)
{
<h2 class="fw-bold text-center"><i class="bi-lightning-charge text-dark" style="font-size: 2rem;"></i> HASTER</h2>
}
@if (ReportItem.VisitTypeEnum.ToLower() == "phone" || ReportItem.OurRef.Contains("T:"))
{
<h5 class="text-center">TELEFONORDRE</h5>
}
@if (ReportItem.StatusTypeEnum is "Quote")
{
<h5 class="text-center">TILBUD</h5>
}
</div>
</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Dato</th>
<td>@ReportItem.OrderDate</td>
<th scope="row">Konto</th>
<td>@ReportItem.Company.Account</td>
</tr>
<tr>
<th scope="col">Telefon</th>
<td>@ReportItem.Company.Phone</td>
<th scope="col">Køber</th>
<td>@ReportItem.YourRef</td>
</tr>
<tr>
<th scope="col">CVR/VAT</th>
<td>@ReportItem.Company.VatNumber</td>
<th scope="col">Rekvisition</th>
<td>@ReportItem.ReferenceNumber</td>
</tr>
<tr>
<th scope="col">Navn</th>
<td>@ReportItem.Company.Name</td>
<th scope="col">Lev.Navn</th>
<td>@ReportItem.DlvName</td>
</tr>
<tr>
<th scope="col">Adresse</th>
<td>@ReportItem.Company.Address1</td>
<th scope="col">Lev.Adresse</th>
<td>@ReportItem.DlvAddress1</td>
</tr>
<tr>
<th scope="col">Adresse</th>
<td>@ReportItem.Company.Address2</td>
<th scope="col">Lev.Adresse</th>
<td>@ReportItem.DlvAddress2</td>
</tr>
<tr>
<th scope="col">Postnr By</th>
<td>@ReportItem.Company.ZipCode @ReportItem.Company.City</td>
<th scope="col">Lev.Postnr By</th>
<td>@ReportItem.DlvZipCity</td>
</tr>
<tr>
<th scope="col">Email</th>
<td colspan="3">@ReportItem.Company.Email</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-striped table-bordered">
<thead>
<tr class="bg-light text-black">
<th scope="col">Antal</th>
<th scope="col">Varnr</th>
<th scope="col">Beskrivelse</th>
<th class="text-end" scope="col">Pris</th>
<th class="text-end" scope="col">R%</th>
<th class="text-end" scope="col">Beløb</th>
</tr>
</thead>
<tbody>
@foreach (var line in ReportItem.Lines)
{
<PageTitle>@Report.ReportData.Name</PageTitle>
<div class="row">
<div class="alert border border-1 border-dark text-center align-content-center">
<h3>@Report.ReportData.Name</h3>
</div>
</div>
<div class="row">
<div class="w-75">
<ReportViewSummaryComponent ReportData="Report.ReportData"/>
</div>
<div class="w-25">
<ReportViewDistanceLedgerComponent ReportData="Report.ReportData"/>
</div>
</div>
<ReportViewActivityListComponent ActivityList="Report.ReportItems" OnShowDocument="ShowDocument"/>
<ReportViewActivityLedgerComponent ReportData="Report.ReportData"/>
<tr>
<td>@line.Quantity</td>
<td>@line.Sku</td>
<td>@line.Description</td>
<td class="text-end">@($"{line.Price:N2}")</td>
<td class="text-end">@($"{line.Discount:N2}")</td>
<td class="text-end">@($"{line.LineSum:N2}")</td>
</tr>
}
else
<tr>
<td colspan="4"></td>
<td>Ordresum</td>
<td class="text-end">@ReportItem.OrderAmount</td>
</tr>
@if (ReportItem.Express)
{
<div class="row">
<div class="col">Ingen rapport data</div>
</div>
<td colspan="4"></td>
<td class="text-end" colspan="2">
<h5 class="fw-bold"><i class="bi-lightning-charge the-fast" style="font-size: 2rem;"></i> HASTER</h5>
</td>
}
</tbody>
</table>
<div class="card">
<div class="card-header">
<div class="card-title">
<div class="h3 pt-3">
Noter
</div>
</div>
</div>
<div class="card-body">
<div class="card-title fw-bold h5">
Kontor
</div>
@ReportItem.OfficeNote
</div>
<div class="card-body">
<div class="card-title fw-bold h5">
Kundekort
</div>
@ReportItem.CrmNote
</div>
</div>
@if (Working)
{
<WorkingThreeDots/>
}

View file

@ -14,16 +14,14 @@
//
using System.Text;
using System.Text.Json;
using Blazored.LocalStorage;
using Blazored.Toast.Services;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using Wonky.Client.Helpers;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpRepository;
using Wonky.Client.Local.Services;
using Wonky.Client.Models;
using Wonky.Entity.DTO;
using Wonky.Entity.Views;
#pragma warning disable CS8618
@ -34,117 +32,45 @@ public partial class ManagerMemberActivityViewPage : IDisposable
{
// #############################################################
[Inject] public HttpInterceptorService Interceptor { get; set; }
[Inject] public ICountryReportRepository ReportRepo { get; set; }
[Inject] public NavigationManager Navigator { get; set; }
[Inject] public ILogger<ManagerMemberActivityViewPage> Logger { get; set; }
[Inject] public ICountryActivityRepository ActivityRepo { get; set; }
[Inject] public ISystemSendMailService MailService { get; set; }
[Inject] public ILocalStorageService Storage { get; set; }
[Inject] public UserPreferenceService PreferenceService { get; set; }
[Inject] public IToastService Toaster { get; set; }
[Inject] public IOrderProcessRepository ProcessRepo { get; set; }
// [Inject] public EventCallback<string> OnShowDocument { get; set; }
[Inject] public ICountryUserInfoRepository UserRepo { get; set; }
[Inject] public ILogger<OfficeOrderViewPage> Logger { get; set; }
[Inject] public IToastService Toast { get; set; }
[Inject] public IUserInfoService UserInfoService { get; set; }
// #############################################################
[Parameter] public string UserId { get; set; } = "";
[Parameter] public string DocumentId { get; set; } = "";
[Parameter] public string ReportDate { get; set; } = "";
// #############################################################
private IJSObjectReference JsModule { get; set; }
private ReportView Report { get; set; } = new();
private List<ReportItemView> Activities { get; set; } = new();
private bool Working { get; set; } = true;
private UserPreference Profile { get; set; } = new();
private string _returnUrl = "";
protected override async Task OnParametersSetAsync()
// #############################################################
private ReportItemView ReportItem { get; set; } = new();
private bool IsNotified { get; set; }
private bool Working { get; set; } = true;
private readonly JsonSerializerOptions _options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
protected override async Task OnInitializedAsync()
{
Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent();
PreferenceService.OnChange += ProfileServiceOnOnChange;
await PreferenceService.SetWorkDate(DateTime.Parse(ReportDate));
await FetchUserReport(ReportDate);
}
/// <summary>
/// Event handler to show the document by Id
/// </summary>
/// <param name="documentId"></param>
private void ShowDocument(string documentId)
{
// shoe order/activity document
// the supervisor version
Navigator.NavigateTo($"/management/members/{UserId}/activities/{ReportDate}/visits/{documentId}");
}
/// <summary>
/// Work date component event handler
/// </summary>
/// <param name="workDate"></param>
private async Task FetchUserReport(string workDate)
{
// remove busy signal if report is empty
if (string.IsNullOrWhiteSpace(Report.ReportData.ReportDate))
{
Working = false;
}
ReportDate = workDate;
// ensure the browser address bar contains the correct link
Navigator.NavigateTo($"/management/members/{UserId}/activities/{workDate}", false, true);
// return if we are already at it
if (Working)
{
return;
}
// reset variables
Report = new ReportView();
Activities = new List<ReportItemView>();
// set busy signal
Working = true;
Logger.LogDebug("UserId => {}", UserId);
// fetch report
Report = await ReportRepo.GetCountryReport(UserId, workDate);
Logger.LogDebug("Report => {}", JsonSerializer.Serialize(Report, new JsonSerializerOptions(JsonSerializerDefaults.Web)));
// extract activities
Activities = Report.ReportItems.Where(x => x.Lines.Any()).ToList();
// store locally
if (!string.IsNullOrWhiteSpace(Report.ReportData.ReportDate))
{
await Storage.SetItemAsync($"{UserId}-{workDate}", Report);
}
// remove busy signal
// fetch order from backend
ReportItem = await ActivityRepo.GetActivity(DocumentId);
Logger.LogDebug("ReportItem => \n {}", JsonSerializer.Serialize(ReportItem, _options));
Working = false;
}
private void ProfileServiceOnOnChange(UserPreference userPreference)
{
Logger.LogDebug("OfficeReportViewPage => ProfileServiceOnOnChange");
Profile = userPreference;
Logger.LogDebug("OfficeReportViewPage => ProfileServiceOnOnChange => Prefs.WorkDate <= {}", Profile.WorkDate);
ReportDate = Profile.WorkDate;
StateHasChanged();
}
public void Dispose()
{
Interceptor.DisposeEvent();
PreferenceService.OnChange -= ProfileServiceOnOnChange;
}
}

View file

@ -17,7 +17,7 @@
@using Wonky.Client.Components
@attribute [Authorize(Roles = "Management,Supervisor")]
@page "/management/members/{UserId}"
@page "/supervisor/members/{UserId}"
<PageTitle>Rapport Arkiv @InfoAdvisor.FirstName @InfoAdvisor.LastName</PageTitle>
<div class="card">

View file

@ -7,14 +7,14 @@ using Wonky.Entity.Views;
namespace Wonky.Client.Pages;
public partial class ManagerMemberViewPage : IDisposable
public partial class ManagerMemberBaseViewPage : IDisposable
{
// #############################################################
[Inject] public HttpInterceptorService Interceptor { get; set; }
[Inject] public IOfficeUserInfoRepository UserRepo { get; set; }
[Inject] public ICountryUserInfoRepository UserRepo { get; set; }
[Inject] public ICountryReportRepository ReportRepo { get; set; }
[Inject] public NavigationManager Navigator { get; set; }
[Inject] public ILogger<ManagerMemberViewPage> Logger { get; set; }
[Inject] public ILogger<ManagerMemberBaseViewPage> Logger { get; set; }
// #############################################################

View file

@ -16,7 +16,7 @@
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Roles = "Supervisor")]
@page "/management"
@page "/supervisor"
<PageTitle>Supervisor</PageTitle>
@ -68,8 +68,8 @@
</table>
</div>
<div class="card-footer">
<a class="btn btn-info" href="/management/members/@user.UserId">Dagsrapporter</a>
<a class="btn btn-primary" href="/management/members/@user.UserId/evaluations">Evalueringer</a>
<a class="btn btn-info" href="/supervisor/members/@user.UserId">Dagsrapporter</a>
<a class="btn btn-primary" href="/supervisor/members/@user.UserId/evaluations">Evalueringer</a>
</div>
</div>
</div>

View file

@ -26,7 +26,7 @@ public partial class ManagerMemberListPage
{
// #############################################################
[Inject] public HttpInterceptorService Interceptor { get; set; }
[Inject] public IOfficeUserInfoRepository UserRepo { get; set; }
[Inject] public ICountryUserInfoRepository UserRepo { get; set; }
// #############################################################
private List<UserInfoListView> Users { get; set; } = new();

View file

@ -1,157 +0,0 @@
@* Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
*@
@using Microsoft.AspNetCore.Authorization
@using Wonky.Client.Components
@attribute [Authorize(Roles = "Management,Supervisor")]
@page "/management/members/{UserId}/activities/{ReportDate}/visits/{DocumentId}"
<PageTitle>@ReportItem.ESalesNumber - @ReportItem.Company.Name</PageTitle>
<table class="table table-sm table-striped d-print-table">
<thead>
<tr>
<th class="p-0" colspan="4">
<div class="bg-light text-dark border border-1 rounded-3 pt-3 mb-2">
<h2 class="fw-bold text-center">@ReportItem.Company.Name</h2>
@if (ReportItem.Express)
{
<h2 class="fw-bold text-center"><i class="bi-lightning-charge text-dark" style="font-size: 2rem;"></i> HASTER</h2>
}
@if (ReportItem.VisitTypeEnum.ToLower() == "phone" || ReportItem.OurRef.Contains("T:"))
{
<h5 class="text-center">TELEFONORDRE</h5>
}
@if (ReportItem.StatusTypeEnum is "Quote")
{
<h5 class="text-center">TILBUD</h5>
}
</div>
</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Dato</th>
<td>@ReportItem.OrderDate</td>
<th scope="row">Konto</th>
<td>@ReportItem.Company.Account</td>
</tr>
<tr>
<th scope="col">Telefon</th>
<td>@ReportItem.Company.Phone</td>
<th scope="col">Køber</th>
<td>@ReportItem.YourRef</td>
</tr>
<tr>
<th scope="col">CVR/VAT</th>
<td>@ReportItem.Company.VatNumber</td>
<th scope="col">Rekvisition</th>
<td>@ReportItem.ReferenceNumber</td>
</tr>
<tr>
<th scope="col">Navn</th>
<td>@ReportItem.Company.Name</td>
<th scope="col">Lev.Navn</th>
<td>@ReportItem.DlvName</td>
</tr>
<tr>
<th scope="col">Adresse</th>
<td>@ReportItem.Company.Address1</td>
<th scope="col">Lev.Adresse</th>
<td>@ReportItem.DlvAddress1</td>
</tr>
<tr>
<th scope="col">Adresse</th>
<td>@ReportItem.Company.Address2</td>
<th scope="col">Lev.Adresse</th>
<td>@ReportItem.DlvAddress2</td>
</tr>
<tr>
<th scope="col">Postnr By</th>
<td>@ReportItem.Company.ZipCode @ReportItem.Company.City</td>
<th scope="col">Lev.Postnr By</th>
<td>@ReportItem.DlvZipCity</td>
</tr>
<tr>
<th scope="col">Email</th>
<td colspan="3">@ReportItem.Company.Email</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-striped table-bordered">
<thead>
<tr class="bg-light text-black">
<th scope="col">Antal</th>
<th scope="col">Varnr</th>
<th scope="col">Beskrivelse</th>
<th class="text-end" scope="col">Pris</th>
<th class="text-end" scope="col">R%</th>
<th class="text-end" scope="col">Beløb</th>
</tr>
</thead>
<tbody>
@foreach (var line in ReportItem.Lines)
{
<tr>
<td>@line.Quantity</td>
<td>@line.Sku</td>
<td>@line.Description</td>
<td class="text-end">@($"{line.Price:N2}")</td>
<td class="text-end">@($"{line.Discount:N2}")</td>
<td class="text-end">@($"{line.LineSum:N2}")</td>
</tr>
}
<tr>
<td colspan="4"></td>
<td>Ordresum</td>
<td class="text-end">@ReportItem.OrderAmount</td>
</tr>
@if (ReportItem.Express)
{
<td colspan="4"></td>
<td class="text-end" colspan="2">
<h5 class="fw-bold"><i class="bi-lightning-charge the-fast" style="font-size: 2rem;"></i> HASTER</h5>
</td>
}
</tbody>
</table>
<div class="card">
<div class="card-header">
<div class="card-title">
<div class="h3 pt-3">
Noter
</div>
</div>
</div>
<div class="card-body">
<div class="card-title fw-bold h5">
Kontor
</div>
@ReportItem.OfficeNote
</div>
<div class="card-body">
<div class="card-title fw-bold h5">
Kundekort
</div>
@ReportItem.CrmNote
</div>
</div>
@if (Working)
{
<WorkingThreeDots/>
}

View file

@ -1,75 +0,0 @@
// Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using System.Text;
using System.Text.Json;
using Blazored.LocalStorage;
using Blazored.Toast.Services;
using Microsoft.AspNetCore.Components;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpRepository;
using Wonky.Client.Local.Services;
using Wonky.Entity.DTO;
using Wonky.Entity.Views;
#pragma warning disable CS8618
namespace Wonky.Client.Pages;
public partial class ManagerMemberVisitViewPage : IDisposable
{
// #############################################################
[Inject] public HttpInterceptorService Interceptor { get; set; }
[Inject] public IAdvisorActivityRepository AdvisorActivityRepo { get; set; }
[Inject] public ISystemSendMailService MailService { get; set; }
[Inject] public ILocalStorageService Storage { get; set; }
[Inject] public IOfficeUserInfoRepository UserRepo { get; set; }
[Inject] public ILogger<OfficeOrderViewPage> Logger { get; set; }
[Inject] public IToastService Toast { get; set; }
[Inject] public IUserInfoService UserInfoService { get; set; }
// #############################################################
[Parameter] public string UserId { get; set; } = "";
[Parameter] public string DocumentId { get; set; } = "";
[Parameter] public string ReportDate { get; set; } = "";
// #############################################################
private ReportItemView ReportItem { get; set; } = new();
private bool IsNotified { get; set; }
private bool Working { get; set; } = true;
private readonly JsonSerializerOptions _options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
protected override async Task OnInitializedAsync()
{
Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent();
// fetch order from backend
ReportItem = await AdvisorActivityRepo.GetReportItem(DocumentId);
Logger.LogDebug("ReportItem => \n {}", JsonSerializer.Serialize(ReportItem, _options));
Working = false;
}
public void Dispose()
{
Interceptor.DisposeEvent();
}
}

View file

@ -31,7 +31,7 @@ public partial class OfficeAdvisorCustomerPagedListPage : IDisposable
[Inject] public HttpInterceptorService Interceptor { get; set; }
[Inject] public ICountryCustomerRepository CustomerRepo { get; set; }
[Inject] public UserPreferenceService UserPreferenceService { get; set; }
[Inject] public IOfficeUserInfoRepository UserRepo { get; set; }
[Inject] public ICountryUserInfoRepository UserRepo { get; set; }
// #############################################################
[Parameter] public string UserId { get; set; } = "";

View file

@ -28,7 +28,7 @@ public partial class OfficeAdvisorListPage :IDisposable
{
// #############################################################
[Inject] public HttpInterceptorService Interceptor { get; set; }
[Inject] public IOfficeUserInfoRepository UserRepo { get; set; }
[Inject] public ICountryUserInfoRepository UserRepo { get; set; }
// #############################################################
[Parameter] public string CountryCode { get; set; } = "";

View file

@ -28,7 +28,7 @@ public partial class OfficeAdvisorReportListPage : IDisposable
// #############################################################
[Inject] public HttpInterceptorService Interceptor { get; set; }
[Inject] public ICountryReportRepository ReportRepo { get; set; }
[Inject] public IOfficeUserInfoRepository UserRepo { get; set; }
[Inject] public ICountryUserInfoRepository UserRepo { get; set; }
[Inject] public NavigationManager Navigator { get; set; }
// #############################################################

View file

@ -43,8 +43,8 @@ public partial class OfficeOrderCreatePage : IDisposable
[Inject] public ICountryCatalogRepository Catalog { get; set; }
[Inject] public ICountryCustomerRepository CustomerRepo { get; set; }
[Inject] public ICountryCustomerHistoryRepository HistoryRepo { get; set; }
[Inject] public ICountryActivityRepository ActivityRepo { get; set; }
[Inject] public IOfficeUserInfoRepository UserRepo { get; set; }
[Inject] public ICountryCustomerActivityRepository CustomerActivityRepo { get; set; }
[Inject] public ICountryUserInfoRepository UserRepo { get; set; }
[Inject] public NavigationManager Navigator { get; set; }
[Inject] public IUserInfoService UserInfoService { get; set; }
@ -114,13 +114,13 @@ public partial class OfficeOrderCreatePage : IDisposable
Logger.LogDebug("OfficeOrderCreate => RequestErpToCrmSync <= {}", Company.HistorySync);
}
// fetch invoices
CompanyInvoices = await HistoryRepo.RequestInvoiceList(CountryCode, CompanyId);
CompanyInvoices = await HistoryRepo.GetInvoiceList(CountryCode, CompanyId);
Logger.LogDebug("OfficeOrderCreate => Invoices => {}", JsonSerializer.Serialize(CompanyInvoices));
// fetch activities
CompanyActivities = await ActivityRepo.RequestActivityList(CompanyId);
CompanyActivities = await CustomerActivityRepo.GetActivityList(CompanyId);
Logger.LogDebug("OfficeOrderCreate => Activities => {}", JsonSerializer.Serialize(CompanyActivities));
// fetch inventory
CompanyInventory = await HistoryRepo.RequestInventory(CountryCode, CompanyId);
CompanyInventory = await HistoryRepo.GetInventory(CountryCode, CompanyId);
CompanyInventory = CompanyInventory.OrderBy(x => x.Description).ToList();
Logger.LogDebug("OfficeOrderCreate => Inventory => {}", JsonSerializer.Serialize(CompanyInventory));
// get sales rep info
@ -310,7 +310,7 @@ public partial class OfficeOrderCreatePage : IDisposable
// debug logging
Logger.LogDebug("CrmNewActivityPage => \n {}", JsonSerializer.Serialize(Activity));
// post to api
var result = await ActivityRepo.CreatePhoneOrder(Company.CompanyId, Activity);
var result = await CustomerActivityRepo.PostPhoneOrder(Company.CompanyId, Activity);
// debug logging
Logger.LogDebug("ApiResponseView => \n {}", JsonSerializer.Serialize(result));
// show result message

View file

@ -35,7 +35,7 @@ public partial class OfficeOrderViewPage : IDisposable
[Inject] public IAdvisorActivityRepository AdvisorActivityRepo { get; set; }
[Inject] public ISystemSendMailService MailService { get; set; }
[Inject] public ILocalStorageService Storage { get; set; }
[Inject] public IOfficeUserInfoRepository UserRepo { get; set; }
[Inject] public ICountryUserInfoRepository UserRepo { get; set; }
[Inject] public ILogger<OfficeOrderViewPage> Logger { get; set; }
[Inject] public IToastService Toast { get; set; }
[Inject] public IUserInfoService UserInfoService { get; set; }

View file

@ -66,15 +66,16 @@ builder.Services.AddScoped<IAdvisorReportRepository, AdvisorReportRepository>();
builder.Services.AddScoped<IAdvisorWorkplaceRepository, AdvisorWorkplaceRepository>();
// administrative repositories
builder.Services.AddScoped<ICountryCustomerHistoryRepository, CountryCustomerHistoryRepository>();
builder.Services.AddScoped<ICountryActivityRepository, CountryActivityRepository>();
builder.Services.AddScoped<ICountryCustomerActivityRepository, CountryCustomerActivityRepository>();
builder.Services.AddScoped<ICountryCatalogRepository, CountryCatalogRepository>();
builder.Services.AddScoped<ICountryCustomerRepository, CountryCustomerRepository>();
builder.Services.AddScoped<ICountryReportRepository, CountryReportRepository>();
builder.Services.AddScoped<ISystemLabelsRepository, SystemLabelsRepository>();
builder.Services.AddScoped<ISystemTextsRepository, SystemTextsRepository>();
builder.Services.AddScoped<ISystemUserRepository, SystemUserRepository>();
builder.Services.AddScoped<IOfficeUserInfoRepository, OfficeUserInfoRepository>();
builder.Services.AddScoped<ICountryUserInfoRepository, CountryUserInfoRepository>();
builder.Services.AddScoped<IEvaluationRepository, EvaluationRepository>();
builder.Services.AddScoped<ICountryActivityRepository, CountryActivityRepository>();
// warehouse repository
builder.Services.AddScoped<IOrderProcessRepository, OrderProcessRepository>();
// mail service

View file

@ -119,8 +119,8 @@
<AuthorizeView Roles="Management,Supervisor">
<Authorized>
<div class="nav-item px-3">
<NavLink class="nav-link ps-2" href="/management">
<i class="bi-people pe-2" style="font-size:1.3em;" aria-hidden="true"></i> Management
<NavLink class="nav-link ps-2" href="/supervisor">
<i class="bi-people pe-2" style="font-size:1.3em;" aria-hidden="true"></i> Supervisor
</NavLink>
</div>
</Authorized>

View file

@ -29,6 +29,7 @@
"crmTasks": "api/v2/crm/advisors/tasks",
"crmWorkplaceExt": "workplaces",
"officeBase": "api/v2/office",
"officeActivities": "api/v2/office/activities",
"officeAdvisors": "api/v2/office/users/advisors",
"officeCustomers": "api/v2/office/customers",
"officeReports": "api/v2/office/reports",

View file

@ -68,6 +68,11 @@ public class ApiConfig
/// </summary>
public string OfficeBase { get; set; } = "";
/// <summary>
/// Office activity url
/// </summary>
public string OfficeActivities { get; set; } = "";
/// <summary>
/// Application uri for administration of sales representatives
/// </summary>