diff --git a/BeWo/View/Detail/Report/DatenbereinigungView.xaml b/BeWo/View/Detail/Report/DatenbereinigungView.xaml new file mode 100644 index 000000000..77daa8d2d --- /dev/null +++ b/BeWo/View/Detail/Report/DatenbereinigungView.xaml @@ -0,0 +1,284 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BeWo/View/Detail/Report/DatenbereinigungView.xaml.cs b/BeWo/View/Detail/Report/DatenbereinigungView.xaml.cs new file mode 100644 index 000000000..5d58f2641 --- /dev/null +++ b/BeWo/View/Detail/Report/DatenbereinigungView.xaml.cs @@ -0,0 +1,173 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Policy; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; +using System.Windows.Media; +using System.Windows.Navigation; +using System.Windows.Threading; +using BeWo.Core; +using BeWo.ServiceProxy; +using BeWo.View.Windows; +using BeWo.ViewModel; +using BeWo.ViewModel.ListViewModel; + +using BS.Shared; +using BS.Shared.Core; +using BS.Shared.DataContracts; +using BS.Shared.DataContracts.Compact; +using BS.Shared.Extensions; +using BS.Shared.Translation; +using DevExpress.Xpf.Editors; +using DevExpress.Xpf.Grid; +using Microsoft.Win32; +using Newtonsoft.Json; + +namespace BeWo.View.Detail.Report +{ + public partial class DatenbereinigungView : BeWoView + { + + public DatenbereinigungView() + { + this.InitializeComponent(); + editJahre.Value = 10; + button_reload.Focus(); + CheckRights(); + + + } + + private void CheckRights() + { + if (!BeWoApp.AppSettings.AllowStorno) + { + ColumnButtons.MinWidth = 67; + } + + } + + private void RefreshList() + { + DateTime? start = null; + DateTime? end = null; + + //bool filterByInvoiceDate = radioFilterByInvoiceDate.IsChecked.Value; + var tid = TableID.Customer; + if (radioEmployee.IsChecked == true) { + tid = TableID.Employee; + } else if (radioPersonen.IsChecked == true) { + tid = TableID.Person; + } + + int anzahlJahre = (int)editJahre.Value; + + ServiceFacade.DoOperationsServiceAsync(s => s.GetInactivePersons(anzahlJahre, tid), UpdateList); + } + + private void UpdateList(IList dcList) + { + this.Dispatcher.BeginInvoke( + DispatcherPriority.Normal, + (Action)delegate + { + //ViewModel.UpdateList(dcList); + this.datagrid_inactiveData.ItemsSource = dcList; + this.gridView.BestFitColumns(); + }); + } + + private void ReloadButton_OnClick(object sender, RoutedEventArgs e) + { + RefreshList(); + } + + private void btn_delete_Click(object sender, RoutedEventArgs e) + { + var vm = this.datagrid_inactiveData.GetCurrentValue(); + + if (MessageBox.Show("Sind Sie sicher, dass Sie die gewählte Rechnung löschen möchten?", "Rechnung löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes) + { + + } + + } + + private void btn_anonymisieren_Click(object sender, RoutedEventArgs e) + { + var vm = this.datagrid_inactiveData.GetCurrentValue(); + + if (MessageBox.Show("Sind Sie sicher, dass Sie die gewählte Rechnung löschen möchten?", "Rechnung löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes) + { + + } + + } + + private void gridView_Loaded(object sender, RoutedEventArgs e) + { + this.gridView.BestFitColumns(); + } + + private void button_checkAll_Click(object sender, RoutedEventArgs e) + { + var visible = GetVisibleVMs(); + foreach (var item in visible) + { + item.IsChecked = true; + } + + datagrid_inactiveData.RefreshData(); + } + + private void button_uncheckAll_Click(object sender, RoutedEventArgs e) + { + var visible = GetVisibleVMs(); + foreach (var item in visible) + { + item.IsChecked = false; + } + + datagrid_inactiveData.RefreshData(); + } + + private void button_deleteAll_Click(object sender, RoutedEventArgs e) + { + + } + + private void button_anonymisierenAll_Click(object sender, RoutedEventArgs e) + { + + } + + private IList GetVisibleVMs() + { + var list = new List(); + + var items = datagrid_inactiveData.ItemsSource as IList; + + if (items != null) + { + for (int i = 0; i < items.Count; i++) + { + if (datagrid_inactiveData.IsRowVisible(i)) + { + var vm = datagrid_inactiveData.GetRow(i) as InactivePersonDC; + if (vm != null) + { + list.Add(vm); + } + } + } + } + + return list; + } + + } +} \ No newline at end of file diff --git a/BeWoPlanerMobil/Controllers/MainController.cs b/BeWoPlanerMobil/Controllers/MainController.cs index 49182d7d9..ec8f7a80e 100644 --- a/BeWoPlanerMobil/Controllers/MainController.cs +++ b/BeWoPlanerMobil/Controllers/MainController.cs @@ -383,6 +383,8 @@ namespace BeWoPlanerMobil.Controllers Model.SelectedZeitraum = new NullableDateTimeSpan(Model.LastSelectedServiceRecordMonth.Date.GetFirstOfMonth(), Model.LastSelectedServiceRecordMonth.Date.GetLastOfMonth()); } + Model.AiVoiceMode = UserSettingsUtils.GetSettingValueAsInteger(userSettings, SettingsKeys.AiVoiceMode); + CalculateSelectedDayCount(Model.LastSelectedServiceRecordTimeIntervalDays, Model.LastSelectedServiceRecordMonth, Model.SelectedZeitraum?.StartDate, Model.SelectedZeitraum?.EndDate, null); var customerFilter = MobileUserSettingsUtils.GetSettingValueAsEnum(userSettings, SettingsKeys.CustomerFilterInZeiterfassung, CustomerFilterEnum.MyCustomer); @@ -3563,35 +3565,65 @@ namespace BeWoPlanerMobil.Controllers return View("Main", Model); } + + [HttpPost] + [Authorize] + public ActionResult SetAiVoiceMode(string mode) + { + SkipModelInitialization = true; + Model.AiVoiceMode = mode == "1" ? 1 : 0; + + UpdateUserSettingsWithoutReload(SettingsKeys.AiVoiceMode, Model.AiVoiceMode.ToString()); + + return new HttpStatusCodeResult(200); + } + /// - /// Ermittelt die externe URL, die beim Klick auf den Test-Button aufgerufen werden soll. - /// Die callbackUrl wird als Parameter mitgegeben, damit das externe System sie verwenden kann. + /// Ermittelt die externe URL, die beim Klick auf den AI-Voice-Button aufgerufen werden soll. + /// Die callId wird server-seitig als GUID erzeugt (kryptographisch sicher) und zusammen + /// mit der URL an den Client zurückgegeben. /// [HttpGet] [Authorize] - public JsonResult GetExternalCallUrl(string callId, string callbackUrl) + public JsonResult GetExternalCallUrl() { + try { + SkipModelInitialization = true; + // CallId server-seitig erzeugen – Guid.NewGuid() ist kryptographisch sicher (128-Bit) + // In der Session speichern – der Browser bekommt sie nie zu sehen + var callId = Guid.NewGuid().ToString("N"); + Session["ExternalCallId"] = callId; + + // CallbackUrl server-seitig zusammenbauen + var callbackUrl = Url.Action("ExternalCallCallback", "Main", new { callId }, Request.Url.Scheme); + var externalUrl = ""; if (Mandator?.OwnChatCode != null) { var ts = new TranscriptionService(); - var avd = ts.InitTranskription(MobileSessionFacade.Tenant, false); + var sendOwnChatMessage = Model.AiVoiceMode == 0 ? false : true; - externalUrl = avd.OwnChatUrl; + var avd = ts.InitTranskription(MobileSessionFacade.Tenant, sendOwnChatMessage); - if (!string.IsNullOrEmpty(callId) && !string.IsNullOrEmpty(avd.Token)) + if (!sendOwnChatMessage) + { + externalUrl = avd.OwnChatUrl; + } + else + { + avd.OwnChatUrl = null; + } + + + if (!string.IsNullOrEmpty(avd.Token)) { _externalCallTokens[callId] = ts.MapAiVoiceDataDC(avd); } Log.Info($"GetExternalCallUrl: {callId}. Url = {externalUrl}, Transkription startet!"); - //var externalBaseUrl = "https://example.com/external-service"; - //var externalUrl = externalBaseUrl - // + "?callbackUrl=" + Uri.EscapeDataString(callbackUrl) - // + "&callId=" + Uri.EscapeDataString(callId); } else { @@ -3646,12 +3678,15 @@ namespace BeWoPlanerMobil.Controllers /// [HttpGet] [Authorize] - public JsonResult CheckExternalCallStatus(string callId) + public JsonResult CheckExternalCallStatus() { + var callId = Session["ExternalCallId"] as string; + if(!string.IsNullOrEmpty(callId) && _externalCallResults.TryRemove(callId, out var data)) { _externalCallStatusMessages.TryRemove(callId, out _); _externalCallTokens.TryRemove(callId, out _); + Session.Remove("ExternalCallId"); return Json(new { completed = true, data }, JsonRequestBehavior.AllowGet); } @@ -3668,10 +3703,14 @@ namespace BeWoPlanerMobil.Controllers statusMessage = avd.StatusMessage; - if (!String.IsNullOrEmpty(statusMessage) && statusMessage.Contains("klicken Sie auf den Link")) + if (!String.IsNullOrEmpty(avd.OwnChatUrl)) // Wenn nicht null, dann wurde die Spracheingabe über direkt Link gestartet { - statusMessage = "Sollte die Aufnahme nicht starten, prüfen Sie bitte, ob ownChat korrekt installiert ist."; + if (!String.IsNullOrEmpty(statusMessage) && statusMessage.Contains("klicken Sie auf den Link")) + { + statusMessage = "Warte auf Beendigung der Aufzeichnung in ownChat...\r\nHINWEIS: Wenn ownChat auf diesem Gerät nicht installiert ist, ist die Spracheingabe nicht möglich. In diesem Fall brechen Sie den Vorgang bitte ab. Wenn Sie ownChat auf einem anderen Gerät nutzen, können Sie in den Einstellungen auch in den Push-Modus wechseln."; + } } + if (!String.IsNullOrEmpty(avd.TranskriptionText)) { statusMessage = "Transkription erfolgreich durchgeführt"; @@ -3708,13 +3747,15 @@ namespace BeWoPlanerMobil.Controllers /// [HttpPost] [Authorize] - public ActionResult CancelExternalCall(string callId) + public ActionResult CancelExternalCall() { + var callId = Session["ExternalCallId"] as string; if(!string.IsNullOrEmpty(callId)) { _externalCallResults.TryRemove(callId, out _); _externalCallStatusMessages.TryRemove(callId, out _); _externalCallTokens.TryRemove(callId, out _); + Session.Remove("ExternalCallId"); } return new HttpStatusCodeResult(200); diff --git a/BeWoPlanerMobil/Models/BaseSessionModel.cs b/BeWoPlanerMobil/Models/BaseSessionModel.cs index 8c1acde26..237e56587 100644 --- a/BeWoPlanerMobil/Models/BaseSessionModel.cs +++ b/BeWoPlanerMobil/Models/BaseSessionModel.cs @@ -9,6 +9,8 @@ namespace BeWoPlanerMobil.Models [Serializable] public abstract class BaseSessionModel { + public int AiVoiceMode { get; set; } + public Dictionary Collapsibles2IsShown { get; set; } = new Dictionary(); public virtual void ResetValues() diff --git a/BeWoPlanerMobil/Models/MainModel.cs b/BeWoPlanerMobil/Models/MainModel.cs index 1517bf51c..a85460cc3 100644 --- a/BeWoPlanerMobil/Models/MainModel.cs +++ b/BeWoPlanerMobil/Models/MainModel.cs @@ -820,6 +820,8 @@ namespace BeWoPlanerMobil.Models public bool IsShowingDurationInHours { get; set; } + public int AiVoiceMode { get { return MainSessionModel.AiVoiceMode; } set { MainSessionModel.AiVoiceMode = value; } } // 0 = direct, 1 = Link senden + public string SelectedDurationUnit => IsShowingDurationInHours ? "Stunden" : "Minuten"; public DateTime LastSelectedServiceRecordMonth { get; set; } diff --git a/BeWoPlanerMobil/Views/Main/SingleBookingPartial.cshtml b/BeWoPlanerMobil/Views/Main/SingleBookingPartial.cshtml index 1c00c6258..d4a34c8c5 100644 --- a/BeWoPlanerMobil/Views/Main/SingleBookingPartial.cshtml +++ b/BeWoPlanerMobil/Views/Main/SingleBookingPartial.cshtml @@ -170,37 +170,35 @@