diff --git a/Wonky.Client/Components/ReportItemComponent.razor b/Wonky.Client/Components/ReportItemComponent.razor index cb7e94d0..a0f01e18 100644 --- a/Wonky.Client/Components/ReportItemComponent.razor +++ b/Wonky.Client/Components/ReportItemComponent.razor @@ -88,6 +88,10 @@ Lev.Postnr By @ReportItem.DlvZipCity + + Email + @ReportItem.Company.Email + diff --git a/Wonky.Client/Helpers/Utils.cs b/Wonky.Client/Helpers/Utils.cs index 901f5122..c9af8164 100644 --- a/Wonky.Client/Helpers/Utils.cs +++ b/Wonky.Client/Helpers/Utils.cs @@ -14,6 +14,7 @@ // using System.Net.Mail; +using System.Text.RegularExpressions; using Wonky.Client.Models; namespace Wonky.Client.Helpers; @@ -23,6 +24,29 @@ namespace Wonky.Client.Helpers; /// public static class Utils { + /// + /// Sanitize string by removing everything but digits + /// + /// + /// + public static string StringToDigits(string digitString) + { + if (string.IsNullOrWhiteSpace(digitString)) + return ""; + var regexObj = new Regex(@"[^\d]"); + return regexObj.Replace(digitString, ""); + } + + /// + /// Validate string is only numbers + /// + /// + /// + private static bool IsDigitsOnly(string check) + { + return check.All(c => c is >= '0' and <= '9'); + } + public static bool Validate(ValidateType validateType, string toValidate) { return validateType switch diff --git a/Wonky.Client/Helpers/VatUtils.cs b/Wonky.Client/Helpers/VatUtils.cs index c0678466..27a40c9a 100644 --- a/Wonky.Client/Helpers/VatUtils.cs +++ b/Wonky.Client/Helpers/VatUtils.cs @@ -32,7 +32,7 @@ public class VatUtils if (string.IsNullOrWhiteSpace(vatNumber) || string.IsNullOrWhiteSpace(countryCode)) return false; - var sanitisedVat = SanitizeVatNumber(vatNumber); + var sanitisedVat = Utils.StringToDigits(vatNumber); return countryCode.ToUpperInvariant() switch { @@ -42,30 +42,7 @@ public class VatUtils _ => false }; } - - /// - /// Sanitize Vat remove everything but digits - /// - /// - /// - public static string SanitizeVatNumber(string vatNumber) - { - if (string.IsNullOrWhiteSpace(vatNumber)) - return ""; - var regexObj = new Regex(@"[^\d]"); - return regexObj.Replace(vatNumber, ""); - } - /// - /// Validate string is only numbers - /// - /// - /// - private static bool IsDigitsOnly(string check) - { - return check.All(c => c is >= '0' and <= '9'); - } - /// /// Validate Danish Vat number format /// diff --git a/Wonky.Client/HttpRepository/ISystemSendSmsService.cs b/Wonky.Client/HttpRepository/ISystemSendSmsService.cs new file mode 100644 index 00000000..c7867caf --- /dev/null +++ b/Wonky.Client/HttpRepository/ISystemSendSmsService.cs @@ -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.DTO; +using Wonky.Entity.Views; + +namespace Wonky.Client.HttpRepository; + +/// +/// Interface for sending emai +/// +public interface ISystemSendSmsService +{ + /// + /// Send Mail + /// + /// + /// + /// + Task SendSms(ShortMessage message); +} \ No newline at end of file diff --git a/Wonky.Client/HttpRepository/SystemSendSmsService.cs b/Wonky.Client/HttpRepository/SystemSendSmsService.cs new file mode 100644 index 00000000..8ae5a48c --- /dev/null +++ b/Wonky.Client/HttpRepository/SystemSendSmsService.cs @@ -0,0 +1,66 @@ +// 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 SystemSendSmsService : ISystemSendSmsService +{ + private readonly JsonSerializerOptions? _options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true + }; + + private readonly NavigationManager _navigation; + private ILogger _logger; + private readonly HttpClient _client; + private readonly ApiConfig _api; + + public SystemSendSmsService(HttpClient client, ILogger logger, + NavigationManager navigation, IOptions configuration) + { + _client = client; + _logger = logger; + _navigation = navigation; + _api = configuration.Value; + } + + /// + /// Send Mail + /// + /// + /// + public async Task SendSms(ShortMessage message) + { + var response = await _client.PostAsJsonAsync($"{_api.ServicesSms}", message, _options); + if (!response.IsSuccessStatusCode) + return new ApiResponseView + { + Code = (int)response.StatusCode, + Message = $"{response.ReasonPhrase}: {await response.Content.ReadAsStringAsync()}", + IsSuccess = false, + Id = "" + }; + var content = await response.Content.ReadAsStringAsync(); + return JsonSerializer.Deserialize(content, _options); + } +} \ No newline at end of file diff --git a/Wonky.Client/OverlayCustomer/CustomerActivityViewOverlay.razor b/Wonky.Client/OverlayCustomer/CustomerActivityViewOverlay.razor index 80dd4a2a..e7b88e7e 100644 --- a/Wonky.Client/OverlayCustomer/CustomerActivityViewOverlay.razor +++ b/Wonky.Client/OverlayCustomer/CustomerActivityViewOverlay.razor @@ -63,12 +63,12 @@
- +
+ +
+ @foreach (var recipient in Recipients) + { +
+ + +
+ } +
+
+
+ +
+
+ +
+
+
+ Status Kode: @SmsResponse.Code +
+
+ Meddelelse: @SmsResponse.Message +
+
+
\ No newline at end of file diff --git a/Wonky.Client/Pages/SystemMaintenanceMessage.razor.cs b/Wonky.Client/Pages/SystemMaintenanceMessage.razor.cs new file mode 100644 index 00000000..4075407f --- /dev/null +++ b/Wonky.Client/Pages/SystemMaintenanceMessage.razor.cs @@ -0,0 +1,85 @@ +using System.Text.Json; +using Blazored.Toast.Services; +using Microsoft.AspNetCore.Components; +using Wonky.Client.Helpers; +using Wonky.Client.HttpInterceptors; +using Wonky.Client.HttpRepository; +using Wonky.Entity.DTO; +using Wonky.Entity.Views; + +namespace Wonky.Client.Pages; + +public partial class SystemMaintenanceMessage +{ + [Inject] public HttpInterceptorService Interceptor { get; set; } + [Inject] public ISystemUserRepository UserRepo { get; set; } + [Inject] public ISystemSendSmsService SmsService { get; set; } + [Inject] public ILogger Logger { get; set; } + [Inject] public IToastService Toaster { get; set; } + + private List Users { get; set; } + private ShortMessage Message { get; set; } = new(); + private List Recipients { get; set; } = new(); + private ApiResponseView SmsResponse { get; set; } = new(); + private bool Working { get; set; } = true; + private bool MsgSent { get; set; } + + private readonly JsonSerializerOptions _options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true + }; + + protected override async Task OnInitializedAsync() + { + Interceptor.RegisterEvent(); + Interceptor.RegisterBeforeSendEvent(); + + Users = await UserRepo.GetUsers(); + + var allRecipients = Users.Where(x => Utils.StringToDigits(x.PhoneNumber) != string.Empty) + .Select(x => new Recipient + { + Mobile = Utils.StringToDigits(x.PhoneNumber), + Name = x.FullName + }).ToList(); + Recipients = (from r in allRecipients select r).DistinctBy(x => x.Mobile).ToList(); + + Working = false; + } + + private async Task SendMessage() + { + Working = true; + var recipients = (from recipient in Recipients where recipient.Enabled select recipient.Mobile).ToList(); + if (!recipients.Any()) + { + Toaster.ShowError("Der er ingen modtagere valgt!"); + return; + } + + if (string.IsNullOrWhiteSpace(Message.Body)) + { + Toaster.ShowError("Meddelelsesfeltet er tomt!"); + return; + } + Message.From = "Innotec IT"; + Message.To = string.Join(",", recipients); + + Logger.LogDebug("{}", JsonSerializer.Serialize(Message, _options)); + + SmsResponse = await SmsService.SendSms(Message); + if (SmsResponse.Code == 201) + { + MsgSent = true; + } + Working = false; + + } +} + +internal sealed class Recipient +{ + public bool Enabled { get; set; } + public string Name { get; set; } + public string Mobile { get; set; } +} \ No newline at end of file diff --git a/Wonky.Client/Pages/SystemUserViewEditPage.razor b/Wonky.Client/Pages/SystemUserViewEditPage.razor index 13eb0ef6..7225d541 100644 --- a/Wonky.Client/Pages/SystemUserViewEditPage.razor +++ b/Wonky.Client/Pages/SystemUserViewEditPage.razor @@ -15,7 +15,10 @@ @using Microsoft.AspNetCore.Authorization +@using Microsoft.AspNetCore.Authorization.Infrastructure @using Wonky.Client.Components +@using System.Security.Principal +@using Wonky.Client.Models @attribute [Authorize(Roles = "Admin")] @page "/system/users/{UserId}" @@ -27,7 +30,7 @@
- @if (!string.IsNullOrWhiteSpace(UserInfo.UserId)) + @if (!string.IsNullOrWhiteSpace(UserData.UserId)) { @@ -40,15 +43,15 @@ Fornavn
@@ -56,15 +59,15 @@ Email @@ -72,24 +75,41 @@ Sælgernr. - + + + + + + @@ -111,10 +131,9 @@

NULSTIL ADGANGSKODE

-
-

Password politik

-

Mindst 10 tegn bestående af store og små bogstaver samt tal.

-

Du kan teste pasword og danne stærke password på pw.nix.dk

+
+
Password politik
+
Mindst 10 tegn bestående af store og små bogstaver samt tal. Kodeordsgenerator pw.nix.dk
@@ -132,7 +151,7 @@
- +
diff --git a/Wonky.Client/Pages/SystemUserViewEditPage.razor.cs b/Wonky.Client/Pages/SystemUserViewEditPage.razor.cs index eee7030c..d4ff0cd6 100644 --- a/Wonky.Client/Pages/SystemUserViewEditPage.razor.cs +++ b/Wonky.Client/Pages/SystemUserViewEditPage.razor.cs @@ -35,7 +35,7 @@ public partial class SystemUserViewEditPage : IDisposable [Inject] public ISystemUserRepository UserRepo { get; set; } [Inject] public ILogger Logger { get; set; } [Inject] public IToastService Toaster { get; set; } - private UserManagerEditView UserInfo { get; set; } = new(); + private UserManagerEditView UserData { get; set; } = new(); private EditContext UserEditContext { get; set; } private ResetPasswordDto Passwords { get; set; } = new(); private EditContext PasswdContext { get; set; } @@ -53,9 +53,9 @@ public partial class SystemUserViewEditPage : IDisposable Interceptor.RegisterEvent(); Interceptor.RegisterBeforeSendEvent(); - UserInfo = await UserRepo.GetUserInfo(UserId); + UserData = await UserRepo.GetUserInfo(UserId); - UserEditContext = new EditContext(UserInfo); + UserEditContext = new EditContext(UserData); PasswdContext = new EditContext(Passwords); PasswdContext.OnFieldChanged += PwHandleFieldChanged!; @@ -68,7 +68,7 @@ public partial class SystemUserViewEditPage : IDisposable ReadOnly = true; Working = true; Toaster.ShowInfo("Sender data til server ..."); - await UserRepo.UpdateUserInfo(UserId, UserInfo); + await UserRepo.UpdateUserInfo(UserId, UserData); Working = false; Toaster.ShowInfo("Bruger er opdateret ..."); } diff --git a/Wonky.Client/Program.cs b/Wonky.Client/Program.cs index a4348f5f..7ae589f0 100644 --- a/Wonky.Client/Program.cs +++ b/Wonky.Client/Program.cs @@ -75,6 +75,7 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); // mail service builder.Services.AddScoped(); +builder.Services.AddScoped(); // interceptor builder.Services.AddScoped(); // storage diff --git a/Wonky.Client/wwwroot/appsettings.json b/Wonky.Client/wwwroot/appsettings.json index b27806b6..167c1817 100644 --- a/Wonky.Client/wwwroot/appsettings.json +++ b/Wonky.Client/wwwroot/appsettings.json @@ -36,6 +36,7 @@ "servicesGlsId": "", "servicesGlsTrackUrl": "https://www.gls-group.eu/276-I-PORTAL-WEB/content/GLS/DK01/DA/5004.htm?txtAction=71000&txtRefNo=", "servicesMail": "api/v2/services/sendmail", + "servicesSms": "api/v2/services/sms", "servicesVatDk": "api/v2/services/virk", "serviceVatEu": "api/v2/services/vies", "servicesVatNo": "api/v2/services/brReg", diff --git a/Wonky.Entity/Configuration/ApiConfig.cs b/Wonky.Entity/Configuration/ApiConfig.cs index 94fde155..d5a9b3a6 100644 --- a/Wonky.Entity/Configuration/ApiConfig.cs +++ b/Wonky.Entity/Configuration/ApiConfig.cs @@ -108,6 +108,10 @@ public class ApiConfig /// public string ServicesMail { get; set; } = ""; + /// + /// url for sending Short Message + /// + public string ServicesSms { get; set; } = ""; /// /// VAT registrar url Denmark /// diff --git a/Wonky.Entity/DTO/ShortMessage.cs b/Wonky.Entity/DTO/ShortMessage.cs new file mode 100644 index 00000000..b6c3c0c5 --- /dev/null +++ b/Wonky.Entity/DTO/ShortMessage.cs @@ -0,0 +1,12 @@ +using System.ComponentModel.DataAnnotations; + +namespace Wonky.Entity.DTO; + +public class ShortMessage +{ + [Required] [MaxLength(11)] public string From { get; set; } = ""; + + [Required] [MaxLength(1000)] public string To { get; set; } = ""; + + [Required] [MaxLength(100)] public string Body { get; set; } = ""; +} \ No newline at end of file diff --git a/Wonky.Entity/DTO/UserManagerEditView.cs b/Wonky.Entity/DTO/UserManagerEditView.cs index b57ddad4..39a20acf 100644 --- a/Wonky.Entity/DTO/UserManagerEditView.cs +++ b/Wonky.Entity/DTO/UserManagerEditView.cs @@ -31,7 +31,7 @@ public class UserManagerEditView public bool LockoutEnabled { get; set; } public string Passwd { get; set; } = ""; [Required(ErrorMessage = "Telefon nummer skal udfyldes")][MaxLength(20, ErrorMessage = "Der er afsat 20 tegn til telefon nummber")] public string PhoneNumber { get; set; } = ""; - [Required(ErrorMessage = "Medarbejder ID skal udfyldes")][MaxLength(20, ErrorMessage = "Der er afsat 20 tegn til medarbejder ID")] public string SalesRep { get; set; } = ""; + [MaxLength(20, ErrorMessage = "Der er afsat 20 tegn til Sælger No.")] public string SalesRep { get; set; } = ""; public string UserId { get; set; } = ""; public List AssignedRoles { get; set; } = new(); public List AssignedSubjects { get; set; } = new(); diff --git a/Wonky.Entity/Views/ReportItemCustomer.cs b/Wonky.Entity/Views/ReportItemCustomer.cs index b9dfe1c1..19813e75 100644 --- a/Wonky.Entity/Views/ReportItemCustomer.cs +++ b/Wonky.Entity/Views/ReportItemCustomer.cs @@ -54,4 +54,9 @@ public class ReportItemCustomer /// Company address address line 2 /// public string Address2 { get; set; } = ""; + + /// + /// Company email address + /// + public string Email { get; set; } = ""; } \ No newline at end of file
- - + + Efternavn - - + +
- - + + Mobilnummer - - + +
- - + + Landekode - - + +
Spærret - - + + + + Beskrivelse + + +
Roller + @foreach (var role in UserData.AssignedRoles) + { +
+ + +
+ }