Merge branch 'master' of ssh://float.ownsoft.de/git/beyondSoft/BeWo
This commit is contained in:
@@ -1002,6 +1002,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CaritasAichachFriedberg", "
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PerspektiveAnitaNelles", "ReportImp\PerspektiveAnitaNelles\PerspektiveAnitaNelles.csproj", "{D80E7BBD-F017-4FBB-B3D3-5AD9F43C418D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FabiansDatenbank", "ReportImp\FabiansDatenbank\FabiansDatenbank.csproj", "{2B6F428D-8F97-4638-AF6B-907CB98D9869}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|.NET = Debug|.NET
|
||||
@@ -12292,6 +12294,30 @@ Global
|
||||
{D80E7BBD-F017-4FBB-B3D3-5AD9F43C418D}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{D80E7BBD-F017-4FBB-B3D3-5AD9F43C418D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{D80E7BBD-F017-4FBB-B3D3-5AD9F43C418D}.Release|x86.Build.0 = Release|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.Debug|.NET.ActiveCfg = Debug|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.Debug|.NET.Build.0 = Debug|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.DebugRemote|.NET.ActiveCfg = Debug|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.DebugRemote|.NET.Build.0 = Debug|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.DebugRemote|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.DebugRemote|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.DebugRemote|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.DebugRemote|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.DebugRemote|x86.ActiveCfg = Debug|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.DebugRemote|x86.Build.0 = Debug|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.Release|.NET.ActiveCfg = Release|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.Release|.NET.Build.0 = Release|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -12787,6 +12813,7 @@ Global
|
||||
{A65F19C6-A523-4566-8855-9141B9435B95} = {D8A691C5-146D-4613-86CC-438F02FE9106}
|
||||
{279D4AEA-239C-4A2C-91DE-735EB7A72F96} = {D8A691C5-146D-4613-86CC-438F02FE9106}
|
||||
{D80E7BBD-F017-4FBB-B3D3-5AD9F43C418D} = {D8A691C5-146D-4613-86CC-438F02FE9106}
|
||||
{2B6F428D-8F97-4638-AF6B-907CB98D9869} = {D8A691C5-146D-4613-86CC-438F02FE9106}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {FBE985BB-9F0F-4DBB-8F94-ABC37A803FF9}
|
||||
|
||||
@@ -186,7 +186,8 @@
|
||||
<HintPath>..\packages\EntityFramework.6.5.1\lib\net45\EntityFramework.SqlServer.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="log4net, Version=3.1.0.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\log4net.3.1.0\lib\net462\log4net.dll</HintPath>
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\Lib\log4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.4.1.0\lib\net472\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll</HintPath>
|
||||
@@ -237,7 +238,7 @@
|
||||
<Reference Include="System.Numerics.Vectors, Version=4.1.6.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Numerics.Vectors.4.6.1\lib\net462\System.Numerics.Vectors.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\Lib\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
|
||||
</Reference>
|
||||
|
||||
BIN
BeWoPlanerMobil/Content/images/Icon_KI_Funktion_Weiss+Gruen.png
Normal file
BIN
BeWoPlanerMobil/Content/images/Icon_KI_Funktion_Weiss+Gruen.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.8 KiB |
BIN
BeWoPlanerMobil/Content/images/Icon_KI_Funktion_Weiss.png
Normal file
BIN
BeWoPlanerMobil/Content/images/Icon_KI_Funktion_Weiss.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.6 KiB |
@@ -1,17 +1,18 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Security;
|
||||
using BeWo.Data.Access;
|
||||
using BeWo.Data.Access;
|
||||
using BeWo.Data.Entities;
|
||||
using BeWo.Service.DCEntityMapper;
|
||||
using BeWo.Service.ServiceContracts;
|
||||
using BeWo.Service.ServiceContracts.Enhanced;
|
||||
using BeWoPlanerMobil.Models;
|
||||
using BeWoPlanerMobil.Service;
|
||||
using BS.Shared;
|
||||
using BS.Shared.Core;
|
||||
using BS.Shared.DataContracts;
|
||||
using ReportingService.ServiceContracts;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Security;
|
||||
|
||||
namespace BeWoPlanerMobil.Controllers
|
||||
{
|
||||
@@ -26,6 +27,7 @@ namespace BeWoPlanerMobil.Controllers
|
||||
protected readonly IDownloadService DownloadService = new MobileSessionFacade().DownloadService;
|
||||
protected readonly IReportService ReportService = new MobileSessionFacade().ReportService;
|
||||
protected readonly IQueryService QueryService = new MobileSessionFacade().QueryService;
|
||||
protected readonly IAiEnhancedService AiService = new MobileSessionFacade().AiService;
|
||||
|
||||
protected const string LeerzeichenFuerGetMethoden = " ";
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ using BS.Shared;
|
||||
using BS.Shared.Core;
|
||||
using BS.Shared.DataContracts;
|
||||
using BS.Shared.DataContracts.Compact;
|
||||
using BS.Shared.DataContracts.Feature.AI;
|
||||
using BS.Shared.Extensions;
|
||||
using BS.Shared.Services;
|
||||
using DevExpress.Utils.Extensions;
|
||||
@@ -316,8 +317,192 @@ namespace BeWoPlanerMobil.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Authorize]
|
||||
public ActionResult GetAiPromptbausteinFolder()
|
||||
{
|
||||
try
|
||||
{
|
||||
var folders = AiService.GetAiPromptbausteinFolder(AiActionType.ServiceRecordDocumentation).ToList();
|
||||
AddFavoriten(folders);
|
||||
var projected = ProjectAiFolders(folders);
|
||||
|
||||
return new JsonResult
|
||||
{
|
||||
Data = projected,
|
||||
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
|
||||
MaxJsonLength = int.MaxValue
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Response.StatusCode = 500;
|
||||
Response.TrySkipIisCustomErrors = true;
|
||||
return Json(new
|
||||
{
|
||||
error = ex.GetType().Name,
|
||||
message = ex.Message,
|
||||
inner = ex.InnerException?.Message,
|
||||
stack = ex.StackTrace
|
||||
}, JsonRequestBehavior.AllowGet);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize]
|
||||
public ActionResult StartPrompt(long promptOid)
|
||||
{
|
||||
try
|
||||
{
|
||||
var conv = new AiConversationDC
|
||||
{
|
||||
Created = DateTime.Now,
|
||||
Updated = DateTime.Now,
|
||||
ActionType = AiActionType.ServiceRecordDocumentation
|
||||
};
|
||||
|
||||
AiViewContextDC viewContext = CreateAiViewContext();
|
||||
|
||||
conv = AiService.CreateAiConversation(conv, viewContext);
|
||||
|
||||
var messages = AiService.ExecuteAiConversationWithPrompt(conv.Oid.Value, viewContext, promptOid);
|
||||
|
||||
// Die generierte Dokumentation ist die letzte Assistent-Nachricht.
|
||||
var resultMessage = (messages ?? new AiConversationMessageDC[0])
|
||||
.LastOrDefault(m => m.Role == AiConversationMessageRole.Assistent)
|
||||
?? (messages ?? new AiConversationMessageDC[0]).LastOrDefault();
|
||||
|
||||
return Json(new
|
||||
{
|
||||
success = true,
|
||||
text = resultMessage?.Message ?? string.Empty
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("StartPrompt fehlgeschlagen", ex);
|
||||
Response.StatusCode = 500;
|
||||
Response.TrySkipIisCustomErrors = true;
|
||||
return Json(new
|
||||
{
|
||||
success = false,
|
||||
error = ex.GetType().Name,
|
||||
message = ex.Message,
|
||||
inner = ex.InnerException?.Message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Baut den AI-Kontext für die aktuell bearbeitete Einzelbuchung auf:
|
||||
/// Primary = ausgewähltes Betreuungskonzept, Secondary = aktueller Dokumentationstext.
|
||||
/// </summary>
|
||||
private AiViewContextDC CreateAiViewContext()
|
||||
{
|
||||
long customerOid = -1;
|
||||
long scOid = -1;
|
||||
long cbOid = -1;
|
||||
var oids = new List<long>();
|
||||
foreach (var record in Model.ServiceRecords)
|
||||
{
|
||||
oids.Add(record.ServiceRecordOid ?? -1);
|
||||
}
|
||||
|
||||
if (Model.SelectedCostBearerSupportConceptOid.HasValue)
|
||||
{
|
||||
var c2s = DAOFactory.GenericDAO.LoadByID<CostBearer2SupportConcept>(Model.SelectedCostBearerSupportConceptOid.Value);
|
||||
customerOid = c2s.SupportConcept.Customer.Oid.Value;
|
||||
scOid = c2s.SupportConcept.Oid.Value;
|
||||
cbOid = c2s.CostBearer.Oid.Value;
|
||||
}
|
||||
|
||||
var rtn = new Dictionary<TableID, long[]>()
|
||||
{
|
||||
{TableID.Customer, new long[]{ customerOid } },
|
||||
{TableID.SupportConcept, new long[]{ scOid } },
|
||||
{TableID.CostBearer, new long[]{ cbOid } },
|
||||
{TableID.ServiceRecord, oids.ToArray() }
|
||||
};
|
||||
|
||||
|
||||
var dc = new AiViewContextDC()
|
||||
{
|
||||
Primary = scOid,
|
||||
References = rtn
|
||||
};
|
||||
|
||||
return dc;
|
||||
}
|
||||
|
||||
|
||||
private void AddFavoriten(List<AiPromptbausteinFolderDC> folders)
|
||||
{
|
||||
var favoriten = new AiPromptbausteinFolderDC()
|
||||
{
|
||||
Oid = -5,
|
||||
Title = "Favoriten",
|
||||
Description = "Eigene Favoriten",
|
||||
SubPrompts = new List<AiPromptbausteinPromptDC>()
|
||||
};
|
||||
|
||||
AddFavoritenPrompts(folders, favoriten);
|
||||
|
||||
folders.Insert(0, favoriten);
|
||||
|
||||
}
|
||||
|
||||
private void AddFavoritenPrompts(List<AiPromptbausteinFolderDC> folders, AiPromptbausteinFolderDC favoriten)
|
||||
{
|
||||
foreach (var folder in folders)
|
||||
{
|
||||
|
||||
if (folder.SubFolders?.Any() ?? false)
|
||||
AddFavoritenPrompts(folder.SubFolders, favoriten);
|
||||
|
||||
foreach (var prompt in folder.SubPrompts)
|
||||
{
|
||||
if (prompt.IsFavorite)
|
||||
favoriten.SubPrompts.Add(prompt);
|
||||
}
|
||||
|
||||
//foreach (var routine in folder.SubRoutines.VMList)
|
||||
//{
|
||||
// if (routine.IsFavorite)
|
||||
// favoriten.SubRoutines.VMList.Add(routine);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Projiziert die AiPromptbausteinFolderDC-Baumstruktur auf ein schlankes,
|
||||
/// zirkelbezugsfreies Objekt für die JSON-Serialisierung an das UI.
|
||||
/// </summary>
|
||||
private List<object> ProjectAiFolders(List<AiPromptbausteinFolderDC> folders)
|
||||
{
|
||||
if (folders == null)
|
||||
{
|
||||
return new List<object>();
|
||||
}
|
||||
|
||||
return folders.Select(f => (object)new
|
||||
{
|
||||
f.Title,
|
||||
f.Description,
|
||||
SubFolders = ProjectAiFolders(f.SubFolders),
|
||||
SubPrompts = (f.SubPrompts ?? new List<AiPromptbausteinPromptDC>())
|
||||
.Select(p => new
|
||||
{
|
||||
p.Oid,
|
||||
p.Title,
|
||||
p.Description,
|
||||
p.Prompt
|
||||
}).ToList()
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
private void InitSettings()
|
||||
{
|
||||
|
||||
//Mandator Settings
|
||||
Model.ShowBetrag = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.ShowBetrag);
|
||||
Model.ShowMarker = UserSettingsUtils.GetSettingValueAsBool(Model.Mandator.Settings, SettingsKeys.ShowMarker);
|
||||
|
||||
@@ -60,6 +60,8 @@ namespace BeWoPlanerMobil.Models
|
||||
|
||||
public bool HasRightToInsertRessourceAppointments => CheckRight(UserRightType.KalenderRessourcentermineAnlegen) || CheckRight(UserRightType.CreateAll);
|
||||
|
||||
public bool HasRightToSeeAiPromptsInZeiterfassung => CheckRight(UserRightType.AiModulePromptbausteineView) && CheckRight(UserRightType.AiModuleServiceRecordDocu);
|
||||
|
||||
public bool HasRightToUseAiVoice
|
||||
{
|
||||
get
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using System.Web;
|
||||
using BeWo.Service.ServiceContracts;
|
||||
using BeWo.Service.ServiceContracts;
|
||||
using BeWo.Service.ServiceContracts.Enhanced;
|
||||
using BeWo.Service.ServiceImplementations;
|
||||
using BeWo.Service.ServiceImplementations.Enhanced;
|
||||
using BeWoPlanerMobil.Models;
|
||||
using ReportingService.ServiceContracts;
|
||||
using ReportingService.ServiceImplementations;
|
||||
using System.Web;
|
||||
|
||||
namespace BeWoPlanerMobil.Service
|
||||
{
|
||||
@@ -21,6 +23,7 @@ namespace BeWoPlanerMobil.Service
|
||||
DownloadService = new DownloadServiceImp();
|
||||
ReportService = new ReportServiceImp();
|
||||
QueryService = new QueryServiceImp();
|
||||
AiService = new AiEnhancedServiceImp();
|
||||
}
|
||||
|
||||
public ICustomerService CustomerService { get; }
|
||||
@@ -33,6 +36,7 @@ namespace BeWoPlanerMobil.Service
|
||||
public IDownloadService DownloadService { get; }
|
||||
public IReportService ReportService { get; }
|
||||
public IQueryService QueryService { get; }
|
||||
public IAiEnhancedService AiService { get; }
|
||||
|
||||
public static long? LoggedInUserOid
|
||||
{
|
||||
|
||||
@@ -433,7 +433,7 @@
|
||||
@{
|
||||
var sbEmployeeInputValue = string.Empty;
|
||||
|
||||
if(Model.SelectedEmployee?.EmployeeOid is not null)
|
||||
if (Model.SelectedEmployee?.EmployeeOid is not null)
|
||||
{
|
||||
sbEmployeeInputValue = $"value=\"{Model.SelectedEmployee.EmployeeOid}\"";
|
||||
}
|
||||
@@ -445,7 +445,7 @@
|
||||
</div>
|
||||
|
||||
@* ----- Einzelbuchung: Ziele ----- *@
|
||||
@if(Model.SelectedSupportConcept != null && Model.SelectedSupportConcept.Goals.Any())
|
||||
@if (Model.SelectedSupportConcept != null && Model.SelectedSupportConcept.Goals.Any())
|
||||
{
|
||||
<div class="form-row">
|
||||
<div class="col-md mt-2">
|
||||
@@ -490,7 +490,7 @@
|
||||
</div>
|
||||
|
||||
@* ----- Marker ----- *@
|
||||
@if(Model.ShowMarker)
|
||||
@if (Model.ShowMarker)
|
||||
{
|
||||
var markerCheckedValue = Model.SelectedServiceRecord?.ServiceRecordType == ServiceRecordTypeId.Content ? "checked" : string.Empty;
|
||||
|
||||
@@ -505,10 +505,10 @@
|
||||
}
|
||||
|
||||
@* ----- Betrag ----- *@
|
||||
@if(Model.ShowBetrag)
|
||||
@if (Model.ShowBetrag)
|
||||
{
|
||||
var betrag = string.Empty;
|
||||
if(Model.SelectedServiceRecord?.Betrag is > 0)
|
||||
if (Model.SelectedServiceRecord?.Betrag is > 0)
|
||||
{
|
||||
betrag = Model.SelectedServiceRecord.Betrag.Value.ToString("#.00");
|
||||
}
|
||||
@@ -541,10 +541,10 @@
|
||||
|
||||
var afterValidationState = TempData[TempDataConstants.AfterValidationStateKey];
|
||||
|
||||
if(Model.SetStartTimeToEndTimeAfterSave && !Model.IsInEditingMode && afterValidationState is false)
|
||||
if (Model.SetStartTimeToEndTimeAfterSave && !Model.IsInEditingMode && afterValidationState is false)
|
||||
{
|
||||
durationValue = Model.NewDuration?.ToString();
|
||||
if(Model.NewDuration.HasValue)
|
||||
if (Model.NewDuration.HasValue)
|
||||
{
|
||||
durationValue = (Model.NewDuration / divisor).ToString();
|
||||
}
|
||||
@@ -564,7 +564,7 @@
|
||||
<input class="form-control" type="date" name="Datum" id="sb-start-date-input" onchange="calcDuration('sb', false, true, false); window.updateStartDate('sb', $(this).val());" value="@Model.StartDateToEditJSFormat" />
|
||||
</div>
|
||||
</div>
|
||||
@if(Model.IsEndDateVisible)
|
||||
@if (Model.IsEndDateVisible)
|
||||
{
|
||||
<div class="col-md-6 mt-2">
|
||||
<div class="input-group">
|
||||
@@ -592,11 +592,11 @@
|
||||
Von
|
||||
</span>
|
||||
</div>
|
||||
<input class="form-control" type="time" name="Start" id="sb-start-time-input" onchange="calcDuration('sb', false, true, false);window.updateStartTime('sb', $(this).val());" value="@von"/>
|
||||
<input class="form-control" type="time" name="Start" id="sb-start-time-input" onchange="calcDuration('sb', false, true, false);window.updateStartTime('sb', $(this).val());" value="@von" />
|
||||
<span class="input-group-text rounded-0 border-left-0 border-right-0">
|
||||
Bis
|
||||
</span>
|
||||
<input class="form-control" type="time" name="Ende" id="sb-end-time-input" onchange="calcDuration('sb', false, false, true);window.updateEndTime('sb', $(this).val());" value="@bis"/>
|
||||
<input class="form-control" type="time" name="Ende" id="sb-end-time-input" onchange="calcDuration('sb', false, false, true);window.updateEndTime('sb', $(this).val());" value="@bis" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -615,7 +615,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<input type="text" class="form-control" id="sb-duration-input" name="Dauer" onchange="beiDaueraenderung('sb'); window.updateDuration('sb', $(this).val());" value="@durationValue">
|
||||
@if(Model.IsZeiterfassungInStdMin)
|
||||
@if (Model.IsZeiterfassungInStdMin)
|
||||
{
|
||||
<div class="input-group-append">
|
||||
<button id="sb-hours-minutes-dropdown-btn" class="btn btn-outline-primary dropdown-toggle w-100" type="button" data-toggle="dropdown">
|
||||
@@ -633,7 +633,7 @@
|
||||
</div>
|
||||
|
||||
@* ----- Einzelbuchung: Distanz ----- *@
|
||||
@if(Model.ShowDistanceField)
|
||||
@if (Model.ShowDistanceField)
|
||||
{
|
||||
<div class="form-row mt-2">
|
||||
<div class="col-md">
|
||||
@@ -652,7 +652,7 @@
|
||||
}
|
||||
|
||||
@* ----- Einzelbuchung: Textbausteine ----- *@
|
||||
@if(Model.HasRightToSeeTextModules)
|
||||
@if (Model.HasRightToSeeTextModules)
|
||||
{
|
||||
<script type="text/javascript">
|
||||
function textModuleButtonOnClick() {
|
||||
@@ -665,11 +665,184 @@
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@* ----- Einzelbuchung: KI Funktionen ----- *@
|
||||
@if (Model.HasRightToSeeAiPromptsInZeiterfassung)
|
||||
{
|
||||
<script type="text/javascript">
|
||||
|
||||
</script>
|
||||
<div class="form-row mt-2" id="aifunction-container">
|
||||
<div class="col-md">
|
||||
@if (Model.HasRightToUseAiVoice)
|
||||
{
|
||||
<button type="button" class="btn btn-primary float-right mr-1" id="aivoice-button" onclick="startExternalCall();" title="KI-Spracheingabe & Transkription" style="padding: 0 0.6em; overflow: hidden; line-height: 0;"><img src="@Url.Content("~/Content/images/Icon_Mikro_Weiss.png")" alt="KI-Spracheingabe & Transkription" style="height:2.25em; display: block;" /></button>
|
||||
}
|
||||
<button type="button" class="btn btn-primary float-right mr-1" id="aiprompt-btn" style="padding: 0 0.6em; overflow: hidden; line-height: 0;"><img src="@Url.Content("~/Content/images/Icon_KI_Funktion_Weiss+Gruen.png")" alt="KI-Promptbausteine auswählen" style="height:2.25em; display: block;" /></button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!-- KI-Promptbausteine Modal -->
|
||||
<div class="modal fade" id="aiprompt-modal" tabindex="-1" role="dialog" aria-labelledby="aiprompt-modal-title" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="aiprompt-modal-title">KI-Promptbausteine auswählen</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Schließen">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row" style="min-height: 350px;">
|
||||
<div class="col-md-5 border-right" id="aiprompt-tree-col">
|
||||
<div id="aiprompt-tree" style="overflow-y: auto; max-height: 400px;">
|
||||
<div class="text-muted small p-2">Wird geladen…</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7" id="aiprompt-prompts-col">
|
||||
<div id="aiprompt-prompts-list">
|
||||
<div class="text-muted small p-2">Bitte einen Ordner auswählen.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Schließen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
(function () {
|
||||
function buildTree(folders, container, level) {
|
||||
folders.forEach(function (folder) {
|
||||
var indent = level * 16;
|
||||
var item = $('<div class="aiprompt-folder-item" style="cursor:pointer; padding: 4px 6px; border-radius:4px; margin-bottom:2px;">'
|
||||
+ '<span style="display:inline-block; width:' + indent + 'px;"></span>'
|
||||
+ '<span class="aiprompt-folder-toggle mr-1" style="display:inline-block; width:14px;">'
|
||||
+ (folder.SubFolders && folder.SubFolders.length > 0 ? '▶' : ' ')
|
||||
+ '</span>'
|
||||
+ '<span class="aiprompt-folder-label"><strong>' + $('<div>').text(folder.Title).html() + '</strong></span>'
|
||||
+ '</div>');
|
||||
|
||||
var subContainer = null;
|
||||
if (folder.SubFolders && folder.SubFolders.length > 0) {
|
||||
subContainer = $('<div class="aiprompt-subfolders" style="display:none;"></div>');
|
||||
buildTree(folder.SubFolders, subContainer, level + 1);
|
||||
}
|
||||
|
||||
item.on('click', function (e) {
|
||||
e.stopPropagation();
|
||||
$('.aiprompt-folder-item').removeClass('bg-primary text-white').css('color', '');
|
||||
item.addClass('bg-primary text-white');
|
||||
|
||||
if (subContainer) {
|
||||
var expanded = subContainer.is(':visible');
|
||||
subContainer.toggle(!expanded);
|
||||
item.find('.aiprompt-folder-toggle').html(expanded ? '▶' : '▼');
|
||||
}
|
||||
|
||||
showPrompts(folder.SubPrompts || []);
|
||||
});
|
||||
|
||||
container.append(item);
|
||||
if (subContainer) container.append(subContainer);
|
||||
});
|
||||
}
|
||||
|
||||
function showPrompts(prompts) {
|
||||
var list = $('#aiprompt-prompts-list').empty();
|
||||
if (!prompts || prompts.length === 0) {
|
||||
list.html('<div class="text-muted small p-2">Keine Prompts in diesem Ordner.</div>');
|
||||
return;
|
||||
}
|
||||
prompts.forEach(function (p) {
|
||||
var card = $('<div class="card mb-2" style="cursor:pointer;"></div>');
|
||||
var body = $('<div class="card-body p-2"></div>');
|
||||
body.append($('<h6 class="card-title mb-1"></h6>').text(p.Title));
|
||||
if (p.Description) body.append($('<p class="card-text small text-muted mb-0"></p>').text(p.Description));
|
||||
card.append(body);
|
||||
card.on('click', function () {
|
||||
if (p.Oid == null) return;
|
||||
// Prompt server-seitig ausführen und Ergebnis ins Doku-Feld schreiben
|
||||
var $card = $(this);
|
||||
$('#aiprompt-prompts-list .card').css('pointer-events', 'none').css('opacity', '0.5');
|
||||
$card.css('opacity', '1').append(
|
||||
'<div class="aiprompt-loading text-muted small mt-1">'
|
||||
+ '<span class="spinner-border spinner-border-sm mr-1"></span>Wird ausgeführt …</div>');
|
||||
$.ajax({
|
||||
url: '@Url.Action("StartPrompt", "Main")',
|
||||
type: 'POST',
|
||||
data: { promptOid: p.Oid },
|
||||
success: function (resp) {
|
||||
$('#aiprompt-modal').modal('hide');
|
||||
var text = resp && resp.text ? resp.text : '';
|
||||
var activeTextarea = $('textarea:visible:first[id^="sb-doku-textarea"]');
|
||||
if (activeTextarea.length && text) {
|
||||
var current = activeTextarea.val();
|
||||
activeTextarea.val(current ? current + '\n' + text : text).trigger('change');
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
var msg = 'Fehler beim Ausführen des Prompts.';
|
||||
try {
|
||||
var r = JSON.parse(xhr.responseText);
|
||||
if (r && r.message) msg += '\n' + r.message;
|
||||
} catch (e) { }
|
||||
console.error('StartPrompt Fehler:', xhr.status, xhr.responseText);
|
||||
$('.aiprompt-loading').remove();
|
||||
$('#aiprompt-prompts-list .card').css('pointer-events', '').css('opacity', '');
|
||||
alert(msg);
|
||||
}
|
||||
});
|
||||
});
|
||||
list.append(card);
|
||||
});
|
||||
}
|
||||
|
||||
var dataLoaded = false;
|
||||
|
||||
$('#aiprompt-btn').on('click', function () {
|
||||
$('#aiprompt-modal').modal('show');
|
||||
if (dataLoaded) return;
|
||||
$.ajax({
|
||||
url: '@Url.Action("GetAiPromptbausteinFolder", "Main")',
|
||||
type: 'GET',
|
||||
success: function (data) {
|
||||
dataLoaded = true;
|
||||
var tree = $('#aiprompt-tree').empty();
|
||||
if (!data || data.length === 0) {
|
||||
tree.html('<div class="text-muted small p-2">Keine Ordner verfügbar.</div>');
|
||||
return;
|
||||
}
|
||||
buildTree(data, tree, 0);
|
||||
},
|
||||
error: function (xhr, textStatus, errorThrown) {
|
||||
var details = 'Status: ' + xhr.status + ' ' + (xhr.statusText || '')
|
||||
+ '\ntextStatus: ' + textStatus
|
||||
+ '\nerror: ' + errorThrown;
|
||||
if (xhr.responseText) {
|
||||
details += '\n\nAntwort:\n' + xhr.responseText.substring(0, 4000);
|
||||
}
|
||||
console.error('GetAiPromptbausteinFolder Fehler:', details);
|
||||
$('#aiprompt-tree').html(
|
||||
'<div class="text-danger small p-2">Fehler beim Laden der Promptbausteine.<br/>'
|
||||
+ '<pre style="white-space:pre-wrap; font-size:11px; max-height:320px; overflow:auto;">'
|
||||
+ $('<div>').text(details).html()
|
||||
+ '</pre></div>');
|
||||
}
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
}
|
||||
@* ----- Einzelbuchung: Dokumentation ----- *@
|
||||
<div class="form-row">
|
||||
<div class="col-md mt-3">
|
||||
@if(Model.NumberOfDokuTypes == 0)
|
||||
@if (Model.NumberOfDokuTypes == 0)
|
||||
{
|
||||
<div class="form-group my-0">
|
||||
<label for="sb-doku-textarea-5">Dokumentation</label>
|
||||
@@ -679,7 +852,7 @@
|
||||
else
|
||||
{
|
||||
<ul class="nav nav-tabs" role="tab-list">
|
||||
@for(var i = 0; i < Model.Dokutypes.Length; i++)
|
||||
@for (var i = 0; i < Model.Dokutypes.Length; i++)
|
||||
{
|
||||
var currentDokuType = Model.Dokutypes[i];
|
||||
|
||||
@@ -691,7 +864,7 @@
|
||||
}
|
||||
</ul>
|
||||
<div class="tab-content" id="dokufelderTab">
|
||||
@for(var i = 0; i < Model.Dokutypes.Length; i++)
|
||||
@for (var i = 0; i < Model.Dokutypes.Length; i++)
|
||||
{
|
||||
var textareaName = i + 1 < 1 ? "Dokumentation" : "Dokumentation" + (i + 1);
|
||||
|
||||
@@ -728,11 +901,6 @@
|
||||
<button type="button" class="btn btn-primary float-right" id="reset-button" onclick="resetSingleBookingForm();">Abbrechen</button>
|
||||
}
|
||||
|
||||
@if (Model.HasRightToUseAiVoice)
|
||||
{
|
||||
<button type="button" class="btn btn-primary float-right mr-1" id="aivoice-button" onclick="startExternalCall();" title="KI-Spracheingabe & Transkription" style="padding: 0 0.6em; overflow: hidden; line-height: 0;"><img src="@Url.Content("~/Content/images/Icon_Mikro_Weiss.png")" alt="KI-Spracheingabe & Transkription" style="height:2.25em; display: block;" /></button>
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Html.Partial("RestoreServiceRecordInputsPartial", Model)
|
||||
|
||||
@@ -170,6 +170,8 @@
|
||||
<add key="PluginBasePath" value="..\CustomerDlls" />
|
||||
<add key="PluginPath" value="..\CustomerDlls" />
|
||||
<add key="FileRootDirectory" value="\BWP-Files" />
|
||||
|
||||
<add key="AiPromptsUrl" value="https://test2.evplaner.de" />
|
||||
</appSettings>
|
||||
<!--
|
||||
Eine Beschreibung der Änderungen von 'web.config' finden Sie unter 'http://go.microsoft.com/fwlink/?LinkId=235367'.
|
||||
@@ -306,7 +308,7 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.3.0" newVersion="6.0.3.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
|
||||
Binary file not shown.
BIN
Lib/log4net.dll
BIN
Lib/log4net.dll
Binary file not shown.
@@ -12,6 +12,7 @@ using System.ComponentModel.Design;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using log4net;
|
||||
using BS.Shared.Core;
|
||||
using BeWo.ServerUtils.Core;
|
||||
|
||||
namespace AICore.Facade
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@ using BS.Shared.Logger;
|
||||
using log4net;
|
||||
using System.Runtime.CompilerServices;
|
||||
using BS.Shared.Core;
|
||||
using BeWo.ServerUtils.Core;
|
||||
|
||||
namespace AICore.Facade.LLM
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using BS.Shared.Core;
|
||||
using BeWo.ServerUtils.Core;
|
||||
using BS.Shared.Core;
|
||||
using BS.Shared.DataContracts;
|
||||
using BS.Shared.Exceptions;
|
||||
using BS.Shared.Interface;
|
||||
|
||||
30
Server/Components/ServerUtils/Core/LoggerUtils.cs
Normal file
30
Server/Components/ServerUtils/Core/LoggerUtils.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using log4net;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BeWo.ServerUtils.Core
|
||||
{
|
||||
public static class LoggerUtils
|
||||
{
|
||||
private static bool _LoggerInit = false;
|
||||
|
||||
public static void InitLogger()
|
||||
{
|
||||
if (_LoggerInit) return;
|
||||
|
||||
log4net.Config.XmlConfigurator.Configure();
|
||||
|
||||
_LoggerInit = true;
|
||||
}
|
||||
|
||||
public static ILog GetLogger(Type declaringType)
|
||||
{
|
||||
InitLogger();
|
||||
|
||||
return log4net.LogManager.GetLogger(declaringType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,6 +89,7 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="ApiFacade\HttpClientFacade.cs" />
|
||||
<Compile Include="ApiFacade\JsonHttpClientFacade.cs" />
|
||||
<Compile Include="Core\LoggerUtils.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -98,9 +99,7 @@
|
||||
<None Include="app.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Core\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Shared\Shared.csproj">
|
||||
<Project>{2f50b83d-a3f0-4ec4-979a-3f9b7e3d8ed4}</Project>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using BS.Shared.Core;
|
||||
using BeWo.ServerUtils.Core;
|
||||
using BS.Shared.Core;
|
||||
using System;
|
||||
using System.ServiceModel.Configuration;
|
||||
|
||||
|
||||
@@ -389,7 +389,13 @@ namespace BeWo.Service.Plugins
|
||||
var actionType = conversation.ActionType;
|
||||
var context_Type = config.Context_Type;
|
||||
|
||||
var context_loaded = AiContextLoader.LoadContext(actionType, view_context, prompt?.SamplesCount);
|
||||
var sampleCount = prompt?.SamplesCount;
|
||||
if(prompt is object && !prompt.IsOwnsoftPrompt)
|
||||
{
|
||||
sampleCount = null;
|
||||
}
|
||||
|
||||
var context_loaded = AiContextLoader.LoadContext(actionType, view_context, sampleCount);
|
||||
var configPath = getPromptPath(actionType);
|
||||
var system_prompt = AiSystemPromptFactory.BuildContext(actionType, configPath, context_loaded, context_Type);
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using BeWo.Data.Access;
|
||||
using BeWo.ServerUtils.Core;
|
||||
using BeWo.Service.Core;
|
||||
using BS.Shared.Core;
|
||||
using System;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using BeWo.Service.Core;
|
||||
using BeWo.ServerUtils.Core;
|
||||
using BeWo.Service.Core;
|
||||
using BS.Shared.Core;
|
||||
using DevExpress.CodeParser.Diagnostics;
|
||||
using log4net;
|
||||
|
||||
@@ -9118,7 +9118,7 @@ namespace BeWo.Service.ServiceImplementations
|
||||
try
|
||||
{
|
||||
var list = new List<InactivePersonDC>();
|
||||
//return list;
|
||||
return list;
|
||||
var sql = @"select null, p.Oid as personoid, p.FirstName, p.LastName, p.DateOfBirth, a.Street as Strasse, a.PostalCode as PLZ, a.Town as Ort, p.insts from person p
|
||||
left join address a on p.Addressoid = a.Oid
|
||||
where (p.isactive = 0 or p.isactive = 2) and (p.SystemEntryID is null || p.SystemEntryID != -1)
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
using log4net;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BS.Shared.Core
|
||||
{
|
||||
public static class LoggerUtils
|
||||
{
|
||||
private static bool _LoggerInit = false;
|
||||
|
||||
public static void InitLogger()
|
||||
{
|
||||
if(_LoggerInit) return;
|
||||
|
||||
log4net.Config.XmlConfigurator.Configure();
|
||||
|
||||
_LoggerInit = true;
|
||||
}
|
||||
|
||||
public static ILog GetLogger(Type declaringType)
|
||||
{
|
||||
InitLogger();
|
||||
|
||||
return log4net.LogManager.GetLogger(declaringType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,9 +103,6 @@
|
||||
<Reference Include="DevExpress.XtraReports.v23.2, Version=23.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL" />
|
||||
<Reference Include="DevExpress.XtraScheduler.v23.2.Core.Desktop, Version=23.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL" />
|
||||
<Reference Include="DevExpress.XtraScheduler.v23.2.Core, Version=23.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL" />
|
||||
<Reference Include="log4net">
|
||||
<HintPath>..\Lib\log4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
@@ -152,7 +149,6 @@
|
||||
<Compile Include="Core\Facade\HttpClientFacade.cs" />
|
||||
<Compile Include="Core\Facade\JsonHttpClientFacade.cs" />
|
||||
<Compile Include="Core\JsonUtils.cs" />
|
||||
<Compile Include="Core\LoggerUtils.cs" />
|
||||
<Compile Include="Core\MailUtils.cs" />
|
||||
<Compile Include="Core\Rule\GkvRules.cs" />
|
||||
<Compile Include="Core\SecurityUtils.cs" />
|
||||
|
||||
Reference in New Issue
Block a user