MH x Claude: Zeitterfassungsdoku kein Pflichtfeld mehr im Falle von Doku ohne Klientenbezug

This commit is contained in:
2026-07-30 14:17:47 +02:00
parent afe4b9cd8c
commit 697683d868
9 changed files with 86 additions and 7 deletions

View File

@@ -2712,6 +2712,7 @@
<Compile Include="ServiceProxy\ServiceFacade.cs" />
<Compile Include="Validation\ValidationBinding.cs" />
<Compile Include="Validation\AttributeValidator.cs" />
<Compile Include="Validation\ICustomerRelatedContext.cs" />
<Compile Include="Validation\DecimalValidator.cs" />
<Compile Include="Validation\ValidationAttribute.cs" />
<Compile Include="Validation\ValidationRules.cs" />

View File

@@ -19,10 +19,19 @@ namespace BeWo.Validation
{
PropertyInfo lPropInfo = null;
object lCurrentObject = this.ExpressionToValidate.DataItem;
// Claude: DataItem des Bindings und Eltern-Objekt des Ziel-Propertys festhalten,
// damit kontextabhaengige Regeln den Klientenbezug auswerten koennen.
// Bei "PrototypeVM.Notice" ist das DataItem die ServiceRecordListVM (kennt
// WithoutClient), bei "Notice" in den EditViews die ServiceRecordVM selbst.
object lDataItem = lCurrentObject;
object lOwner = lCurrentObject;
if (lCurrentObject != null)
{
foreach (var iPropName in this.ExpressionToValidate.ParentBinding.Path.Path.Split("."))
{
lOwner = lCurrentObject; // Claude: vor dem GetValue merken
lPropInfo = lCurrentObject.GetType().GetProperty(iPropName);
lCurrentObject = lPropInfo.GetValue(lCurrentObject, null);
}
@@ -33,7 +42,12 @@ namespace BeWo.Validation
var lAttributes = lPropInfo.GetCustomAttributes(typeof(ValidationAttribute), true);
if (lAttributes.Length > 0)
{
lValid = ((ValidationAttribute) lAttributes[0]).Validate(pValue);
// Claude: DataItem hat Vorrang, weil dort der View-Zustand liegt
// (ServiceRecordListVM.WithoutClient); sonst greift das Eltern-Objekt.
var lContext = (lDataItem as ICustomerRelatedContext)
?? (lOwner as ICustomerRelatedContext);
lValid = ((ValidationAttribute) lAttributes[0]).Validate(pValue, lContext);
}
}
}

View File

@@ -0,0 +1,12 @@
namespace BeWo.Validation
{
// Claude: Kontext fuer klientenabhaengige Validierungsregeln.
// Wird von ValidationRules.EmptyNoticeInNewServiceRecordsAllowed ausgewertet: die
// Dokumentationspflicht (Mandanten-Setting IsServiceRecordNoticeMandatory) gilt nur fuer
// klientenbezogene Zeiterfassungen, also fuer Eintraege mit Customer/Hilfeplan.
public interface ICustomerRelatedContext
{
// Claude: true, wenn der Eintrag zu einem Customer/SupportConcept gehoert.
bool IsCustomerRelated { get; }
}
}

View File

@@ -15,7 +15,9 @@ namespace BeWo.Validation
public ValidationRules ValidationRule { get; set; }
public bool Validate(object pValue)
// Claude: pContext liefert den Klientenbezug fuer EmptyNoticeInNewServiceRecordsAllowed.
// null bedeutet "unbekannt" -> bisheriges Verhalten (Pflichtfeld bleibt).
public bool Validate(object pValue, ICustomerRelatedContext pContext = null)
{
bool lResult = true;
switch (ValidationRule)
@@ -73,7 +75,12 @@ namespace BeWo.Validation
break;
case ValidationRules.EmptyNoticeInNewServiceRecordsAllowed:
if (BeWoApp.AppSettings.IsServiceRecordNoticeMandatory)
// Claude: Dokumentationspflicht greift nur noch bei klientenbezogenen
// Eintraegen (Customer/Hilfeplan). Ohne Klientenbezug - in
// ServiceRecordView2 also bei abgewaehlter CheckBox "chkWithClient" -
// ist die Dokumentation niemals Pflicht.
if (BeWoApp.AppSettings.IsServiceRecordNoticeMandatory
&& (pContext == null || pContext.IsCustomerRelated))
{
if (pValue is string)
{

View File

@@ -370,7 +370,7 @@
Grid.Row="0"
Grid.ColumnSpan="2"
Margin="3,5,3,5"
Content="{markup:Translate Dokumentationstext in der Zeiterfassung Pflichtfeld}"
Content="{markup:Translate Klientenbezogener Dokumentationstext in der Zeiterfassung Pflichtfeld}"
IsChecked="{Binding Path=IsServiceRecordNoticeMandatory}" />
<CheckBox
Grid.Row="1"

View File

@@ -2481,6 +2481,26 @@ namespace BeWo.View.Detail.Zeiterfassung
ButtonZeiterfassungErstellen.Visibility = BeWoApp.AppSettings.ShowKlientenBetreuungszeiten ? Visibility.Visible : Visibility.Collapsed;
}
SetRebookingButtonVisibility();
RevalidateNotice(); // Claude
}
// Claude: Der Klientenbezug entscheidet, ob die Dokumentation Pflichtfeld ist
// (ValidationRules.EmptyNoticeInNewServiceRecordsAllowed). Beim Umschalten der CheckBox
// muss das Notice-Binding neu bewertet werden, sonst bleibt ein bereits angezeigter
// Validierungsfehler stehen bzw. ein neu entstandener wird nicht angezeigt.
private void RevalidateNotice()
{
if (dokumentationsTextBox == null)
{
return;
}
var lExpression = dokumentationsTextBox.GetBindingExpression(TextBox.TextProperty);
if (lExpression != null)
{
lExpression.UpdateSource();
}
}
private void ChkWithClient_Unchecked(object sender, RoutedEventArgs e)
@@ -2509,6 +2529,8 @@ namespace BeWo.View.Detail.Zeiterfassung
}
SetRebookingButtonVisibility();
RevalidateNotice(); // Claude
}
//CB EINKOMMENTIEREN

View File

@@ -13,6 +13,7 @@ using BeWo.Core;
using BeWo.Core.Commands;
using BeWo.Core.Service;
using BeWo.ServiceProxy;
using BeWo.Validation; // Claude: ICustomerRelatedContext
using BeWo.View.Controls.AI;
using BeWo.ViewModel.Controls.AI;
using BeWo.ViewModel.View.AI;
@@ -34,7 +35,8 @@ using DispatcherObject = System.Windows.Threading.DispatcherObject;
namespace BeWo.ViewModel.ListViewModel
{
public class ServiceRecordListVM : AbstractDCListMapperVM<ServiceRecordDC, ServiceRecordVM>, ITextProvider
// Claude: ICustomerRelatedContext -> steuert die Dokumentationspflicht bei der Neuerfassung
public class ServiceRecordListVM : AbstractDCListMapperVM<ServiceRecordDC, ServiceRecordVM>, ITextProvider, ICustomerRelatedContext
{
public static string PropertyName_CustomerNodes = "CustomerNodes";
public static string PropertyName_Information = "Information";
@@ -666,6 +668,14 @@ namespace BeWo.ViewModel.ListViewModel
public bool WithoutClient { get; set; }
// Claude: Klientenbezug fuer die Dokumentationspflicht. In ServiceRecordView2 steuert das
// die CheckBox "chkWithClient" ueber WithoutClient. In Views ohne diese CheckBox
// (z.B. AdditionalServiceView) bleibt WithoutClient false -> Verhalten wie bisher.
public bool IsCustomerRelated
{
get { return !WithoutClient; }
}
protected override Comparison<ServiceRecordVM> Comparison
{
get { return (x, y) => y.StartDate.CompareTo(x.StartDate); }

View File

@@ -21,7 +21,8 @@ using Color = System.Windows.Media.Color;
namespace BeWo.ViewModel
{
public class ServiceRecordVM : AbstractDCMapperVM<ServiceRecordDC>
// Claude: ICustomerRelatedContext -> steuert die Dokumentationspflicht beim Bearbeiten
public class ServiceRecordVM : AbstractDCMapperVM<ServiceRecordDC>, ICustomerRelatedContext
{
public String ATEST { get; set; }
#region Constants and Fields
@@ -1339,6 +1340,18 @@ namespace BeWo.ViewModel
}
}
// Claude: Klientenbezug fuer die Dokumentationspflicht beim Bearbeiten eines bestehenden
// Eintrags (ServiceRecordEditView / ServiceRecordGroupEditView binden direkt an dieses VM).
// Beim Laden aus dem DataContract ist Customer gesetzt, wenn der Eintrag zu einem
// Klienten gehoert - kundenlose Eintraege haben Customer == null.
// Achtung: Am PrototypeVM der Neuerfassung ist Customer immer null; dort liefert
// ServiceRecordListVM.IsCustomerRelated den Kontext (DataItem hat im AttributeValidator
// Vorrang), weil der Kunde erst nach der Validierung an den Klon geschrieben wird.
public bool IsCustomerRelated
{
get { return Customer != null; }
}
[Validation(ValidationRule = ValidationRules.EmptyNoticeInNewServiceRecordsAllowed)]
public string Notice
{