This commit is contained in:
2025-06-10 14:29:34 +02:00
parent 08963fe2f9
commit 3ec64dfc86
30 changed files with 816 additions and 583 deletions

View File

@@ -17,9 +17,9 @@ namespace BeWo.ServiceProxy
public interface IAccountingEnhancedService
{
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IAccountingEnhancedService/CreateXRechnung", ReplyAction="http://tempuri.org/IAccountingEnhancedService/CreateXRechnungResponse")]
[System.ServiceModel.FaultContractAttribute(typeof(BS.Shared.Core.BeWoFault), Action="http://tempuri.org/IAccountingEnhancedService/CreateXRechnungBeWoFaultFault", Name="BeWoFault", Namespace="http://schemas.datacontract.org/2004/07/BS.Shared.Core")]
byte[] CreateXRechnung(long invoice_base_oid, int report_type, string report_url);
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IAccountingEnhancedService/GetXRechnung", ReplyAction="http://tempuri.org/IAccountingEnhancedService/GetXRechnungResponse")]
[System.ServiceModel.FaultContractAttribute(typeof(BS.Shared.Core.BeWoFault), Action="http://tempuri.org/IAccountingEnhancedService/GetXRechnungBeWoFaultFault", Name="BeWoFault", Namespace="http://schemas.datacontract.org/2004/07/BS.Shared.Core")]
BS.Shared.DataContracts.MikePHPContracts.ApiResponse<byte[]> GetXRechnung(long invoice_base_oid, int report_type, string report_url);
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
@@ -56,9 +56,9 @@ namespace BeWo.ServiceProxy
{
}
public byte[] CreateXRechnung(long invoice_base_oid, int report_type, string report_url)
public BS.Shared.DataContracts.MikePHPContracts.ApiResponse<byte[]> GetXRechnung(long invoice_base_oid, int report_type, string report_url)
{
return base.Channel.CreateXRechnung(invoice_base_oid, report_type, report_url);
return base.Channel.GetXRechnung(invoice_base_oid, report_type, report_url);
}
}
}

View File

@@ -160,10 +160,6 @@ namespace BeWo.ServiceProxy
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IAccountingService/StorniereInvoiceBases", ReplyAction="http://tempuri.org/IAccountingService/StorniereInvoiceBasesResponse")]
[System.ServiceModel.FaultContractAttribute(typeof(BS.Shared.Core.BeWoFault), Action="http://tempuri.org/IAccountingService/StorniereInvoiceBasesBeWoFaultFault", Name="BeWoFault", Namespace="http://schemas.datacontract.org/2004/07/BS.Shared.Core")]
void StorniereInvoiceBases(System.Collections.Generic.List<BS.Shared.DataContracts.InvoiceBaseDC> invoices);
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IAccountingService/GetXRechnung", ReplyAction="http://tempuri.org/IAccountingService/GetXRechnungResponse")]
[System.ServiceModel.FaultContractAttribute(typeof(BS.Shared.Core.BeWoFault), Action="http://tempuri.org/IAccountingService/GetXRechnungBeWoFaultFault", Name="BeWoFault", Namespace="http://schemas.datacontract.org/2004/07/BS.Shared.Core")]
BS.Shared.DataContracts.Invoicing.XRechnung.XRechnungResponse GetXRechnung(BS.Shared.DataContracts.Invoicing.XRechnung.XRechnungRequest req);
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
@@ -359,10 +355,5 @@ namespace BeWo.ServiceProxy
{
base.Channel.StorniereInvoiceBases(invoices);
}
public BS.Shared.DataContracts.Invoicing.XRechnung.XRechnungResponse GetXRechnung(BS.Shared.DataContracts.Invoicing.XRechnung.XRechnungRequest req)
{
return base.Channel.GetXRechnung(req);
}
}
}

View File

@@ -20,6 +20,7 @@ using BeWo.ViewModel.ListViewModel;
using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.MikePHPContracts;
using BS.Shared.Extensions;
using BS.Shared.Translation;
using DevExpress.Xpf.Editors;
@@ -651,19 +652,20 @@ namespace BeWo.View.Detail.Accounting
var invoice_type = (int)vm.DataContract.Type;
var report_link = vm.ReportLink;
ServiceFacade.DoAccountingEnhancedServiceAsnyc(
x => x.CreateXRechnung(invoice_base_oid, invoice_type, report_link),
cb =>
ServiceFacade.DoAccountingEnhancedServiceAsnyc<ApiResponse<byte[]>>(
x => x.GetXRechnung(invoice_base_oid, invoice_type, report_link),
response =>
{
if (response.Success)
{
if (cb is byte[] bytes)
{
File.WriteAllBytes(@"C:\Users\ownSoft\Desktop\XRechnung\test.pdf", bytes);
BeWoApp.MainControl.WindowService.ShowERechnungWindow(new MemoryStream(bytes));
}
else
MessageBox.Show("cb is null");
});
BeWoApp.MainControl.WindowService.ShowERechnungWindow(new MemoryStream(response.Data));
}
else
{
MessageBox.Show(response.ToErrorString());
}
}
);
}
}
}

View File

@@ -1,26 +1,47 @@
<localView:BeWoView x:Class="BeWo.View.Detail.Accounting.ServiceInvoiceCreatePopUpView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:localView="clr-namespace:BeWo.View"
xmlns:localViewModel="clr-namespace:BeWo.ViewModel" xmlns:localViewDetail="clr-namespace:BeWo.View.Detail.Accounting"
xmlns:val="clr-namespace:BeWo.Validation" xmlns:uc="clr-namespace:BeWo.Controls;assembly=BeWo.Controls"
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
xmlns:markup="clr-namespace:BeWo.MultiLanguage.Markup"
xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors" Height="Auto" Width="Auto"
HorizontalAlignment="Stretch" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:r="clr-namespace:BeWo.Security"
VerticalAlignment="Stretch" Focusable="True"
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Classic">
<localView:BeWoView
x:Class="BeWo.View.Detail.Accounting.ServiceInvoiceCreatePopUpView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Classic"
xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
xmlns:localView="clr-namespace:BeWo.View"
xmlns:localViewDetail="clr-namespace:BeWo.View.Detail.Accounting"
xmlns:localViewModel="clr-namespace:BeWo.ViewModel"
xmlns:markup="clr-namespace:BeWo.MultiLanguage.Markup"
xmlns:r="clr-namespace:BeWo.Security"
xmlns:s="clr-namespace:System;assembly=mscorlib"
xmlns:uc="clr-namespace:BeWo.Controls;assembly=BeWo.Controls"
xmlns:val="clr-namespace:BeWo.Validation"
Width="Auto"
Height="Auto"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Focusable="True">
<GroupBox Width="1100" Style="{StaticResource PopUpWindowStyle}">
<GroupBox.Header>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="0,0,0,0">
<Image Source="..\..\Ressources\Icons\CoinsDisabled.png" Height="28" />
<TextBox Margin="10,4,0,0" Background="{x:Null}" Foreground="{DynamicResource MainGroupBoxForegroundBrush}"
FontSize="20" BorderBrush="{x:Null}" VerticalAlignment="Stretch" BorderThickness="0,0,0,0"
Padding="0,0,0,0" />
<StackPanel
Margin="0,0,0,0"
VerticalAlignment="Center"
Orientation="Horizontal">
<Image Height="28" Source="..\..\Ressources\Icons\CoinsDisabled.png" />
<TextBox
Margin="10,4,0,0"
Padding="0,0,0,0"
VerticalAlignment="Stretch"
Background="{x:Null}"
BorderBrush="{x:Null}"
BorderThickness="0,0,0,0"
FontSize="20"
Foreground="{DynamicResource MainGroupBoxForegroundBrush}" />
</StackPanel>
</GroupBox.Header>
<Grid Background="{StaticResource ObjectEditBackgroundBrush}">
<GroupBox Margin="10" Header="Rechnung(en) erstellen" Style="{StaticResource ObjectEditGroupBox}">
<GroupBox
Margin="10"
Header="Rechnung(en) erstellen"
Style="{StaticResource ObjectEditGroupBox}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
@@ -38,41 +59,84 @@
<AccessText Margin="2">Klicken Sie anschließend auf "Erstellen".</AccessText>
</StackPanel>
</Label>
<TextBlock x:Name="txtWarnhinweis" Foreground="Red" Grid.Column="1" ></TextBlock>
<TextBlock
x:Name="txtWarnhinweis"
Grid.Column="1"
Foreground="Red" />
<dxg:GridControl x:Name="grid_newInvoices" Margin="3" Grid.Row="1" Grid.ColumnSpan="2" MinHeight="200">
<dxg:GridControl
x:Name="grid_newInvoices"
Grid.Row="1"
Grid.ColumnSpan="2"
MinHeight="200"
Margin="3">
<dxg:GridControl.Columns>
<dxg:GridColumn FieldName="Notice" Header="" FixedWidth="True" Width="24" ReadOnly="True">
<dxg:GridColumn
Width="24"
FieldName="Notice"
FixedWidth="True"
Header=""
ReadOnly="True">
<dxg:GridColumn.CellTemplate>
<DataTemplate>
<Button Content="r" Click="btn_delete_Click" FontFamily="Webdings" Width="18" Height="18"
VerticalAlignment="Center" />
<Button
Width="18"
Height="18"
VerticalAlignment="Center"
Click="btn_delete_Click"
Content="r"
FontFamily="Webdings" />
</DataTemplate>
</dxg:GridColumn.CellTemplate>
</dxg:GridColumn>
<dxg:GridColumn FieldName="InvoiceBase.InvoiceTitle" Header="Über"></dxg:GridColumn>
<dxg:GridColumn FieldName="InvoiceBase.RecipientOrganisation" Header="{markup:Translate EmpfängerSingular}"></dxg:GridColumn>
<dxg:GridColumn FieldName="InvoiceBase.PeriodString" Header="Abrechnungszeitraum"></dxg:GridColumn>
<dxg:GridColumn FieldName="InvoiceBase.InvoiceTitle" Header="Über" />
<dxg:GridColumn FieldName="InvoiceBase.RecipientOrganisation" Header="{markup:Translate EmpfängerSingular}" />
<dxg:GridColumn FieldName="InvoiceBase.PeriodString" Header="Abrechnungszeitraum" />
<dxg:GridColumn FieldName="EndClaim" Header="Betrag">
<dxg:GridColumn.EditSettings>
<dxe:TextEditSettings DisplayFormat="c" Mask="c" MaskType="Numeric"></dxe:TextEditSettings>
<dxe:TextEditSettings
DisplayFormat="c"
Mask="c"
MaskType="Numeric" />
</dxg:GridColumn.EditSettings>
</dxg:GridColumn>
<dxg:GridColumn FieldName="InvoiceBase.Details" Header="Details"></dxg:GridColumn>
<dxg:GridColumn FieldName="InvoiceBase.NeuErstellen" Header="Neu erstellen" ></dxg:GridColumn>
<dxg:GridColumn FieldName="InvoiceBase.DiffErstellen" Header="{markup:Translate Diff.-Rg erstellen}"></dxg:GridColumn>
<dxg:GridColumn FieldName="InvoiceBase.Hinweise" Header="Hinweise"></dxg:GridColumn>
<dxg:GridColumn FieldName="InvoiceBase.Details" Header="Details" />
<dxg:GridColumn FieldName="InvoiceBase.NeuErstellen" Header="Neu erstellen" />
<dxg:GridColumn FieldName="InvoiceBase.DiffErstellen" Header="{markup:Translate Diff.-Rg erstellen}" />
<dxg:GridColumn FieldName="InvoiceBase.Hinweise" Header="Hinweise" />
</dxg:GridControl.Columns>
<dxg:GridControl.View>
<dxg:TableView ShowGroupPanel="False" CellValueChanging="TableView_CellValueChanging"/>
<dxg:TableView CellValueChanging="TableView_CellValueChanging" ShowGroupPanel="False" />
</dxg:GridControl.View>
</dxg:GridControl>
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal" Grid.Row="2" Grid.ColumnSpan="2">
<Button Content=" Für alle neu erstellen auswählen " Click="btn_SelectAllNeu" Margin="3" />
<Button Content=" Für alle Diff-Rg erstellen auswählen " Click="btn_SelectAllDiff" Margin="3" />
<Button Content=" Alle abwählen " Click="btn_DeselectAll" Padding="5 0" Margin="3" />
<Button Content=" Erstellen " x:Name="btn_create" Click="btn_create_Click" Margin="20,3,3,3" />
<Button Content=" Abbrechen " x:Name="btn_cancel" Click="btn_cancel_Click" Margin="3" />
<StackPanel
Grid.Row="2"
Grid.ColumnSpan="2"
HorizontalAlignment="Right"
Orientation="Horizontal">
<Button
Margin="3"
Click="btn_SelectAllNeu"
Content=" Für alle neu erstellen auswählen " />
<Button
Margin="3"
Click="btn_SelectAllDiff"
Content=" Für alle Diff-Rg erstellen auswählen " />
<Button
Margin="3"
Padding="5,0"
Click="btn_DeselectAll"
Content=" Alle abwählen " />
<Button
x:Name="btn_create"
Margin="20,3,3,3"
Click="btn_create_Click"
Content=" Erstellen " />
<Button
x:Name="btn_cancel"
Margin="3"
Click="btn_cancel_Click"
Content=" Abbrechen " />
</StackPanel>
</Grid>
</GroupBox>

View File

@@ -9,12 +9,12 @@
Background="Transparent"
Closed="Window_Closed"
Closing="Window_Closing"
Loaded="Window_Loaded"
ResizeMode="CanResizeWithGrip"
SnapsToDevicePixels="True"
TextOptions.TextFormattingMode="Display"
WindowStartupLocation="CenterOwner"
WindowStyle="None"
Loaded="Window_Loaded">
WindowStyle="None">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>

View File

@@ -59,5 +59,5 @@ namespace BeWo.Data.Access
{
return Session.CreateCriteria(typeof(T), alias).Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active));
}
}
}
}

View File

@@ -13,142 +13,142 @@ using NHibernate.Proxy;
namespace BeWo.Data.Access
{
public class GenericDAO : AbstractBaseDAO
{
internal GenericDAO()
{
}
public class GenericDAO : AbstractBaseDAO
{
internal GenericDAO()
{
}
public virtual void Deactivate(BeWoEntityBase pEntity)
{
Debug.WriteLine($"---->DEACTIVATE von {pEntity.GetType().FullName}");
public virtual void Deactivate(BeWoEntityBase pEntity)
{
Debug.WriteLine($"---->DEACTIVATE von {pEntity.GetType().FullName}");
this.SetActivationType(pEntity, ActivationTypeId.Deleted);
}
this.SetActivationType(pEntity, ActivationTypeId.Deleted);
}
public virtual void Deactivate<T>(IEnumerable<T> pEntitys) where T : BeWoEntityBase, new()
{
if(pEntitys?.FirstOrDefault() is object obj)
{
Debug.WriteLine($"---->DEACTIVATE von {obj.GetType().FullName}");
}
public virtual void Deactivate<T>(IEnumerable<T> pEntitys) where T : BeWoEntityBase, new()
{
if (pEntitys?.FirstOrDefault() is object obj)
{
Debug.WriteLine($"---->DEACTIVATE von {obj.GetType().FullName}");
}
ITransaction lTransaction = this.Session.BeginTransaction();
try
{
foreach (BeWoEntityBase iEntity in pEntitys)
{
iEntity.IsActive = ActivationTypeId.Deleted;
if (iEntity.SystemEntryID == null)
{
this.Session.SaveOrUpdate(iEntity);
}
else
{
throw new InvalidOperationException("Can't delete System Entries");
}
}
lTransaction.Commit();
}
catch (Exception e)
{
lTransaction.Rollback();
throw e;
}
}
public virtual void Delete(BeWoEntityBase pEntity)
{
Debug.WriteLine($"---->DELETE von {pEntity.GetType().FullName}");
if(pEntity.SystemEntryID is null)
{
LogSignatureDeletion(pEntity);
var lTransaction = Session.BeginTransaction();
try
{
Session.Delete(pEntity);
lTransaction.Commit();
}
catch (Exception e)
{
lTransaction.Rollback();
throw e;
}
}
else
{
throw new InvalidOperationException("Can't delete System Entries");
}
}
public virtual void Delete<T>(IEnumerable<T> pEntitys) where T : BeWoEntityBase, new()
{
if(pEntitys?.FirstOrDefault() is object obj)
{
Debug.WriteLine($"---->DELETE von {obj.GetType().FullName}");
}
var entities = pEntitys.ToList();
foreach(var entity in entities)
{
LogSignatureDeletion(entity);
}
var lTransaction = Session.BeginTransaction();
try
{
foreach(var iEntity in entities)
{
if(iEntity.SystemEntryID is null || iEntity.SystemEntryID.Value == SystemEntryID.AdditionalServiceAssessmentSheet)
{
Session.Delete(iEntity);
}
else
{
ITransaction lTransaction = this.Session.BeginTransaction();
try
{
foreach (BeWoEntityBase iEntity in pEntitys)
{
iEntity.IsActive = ActivationTypeId.Deleted;
if (iEntity.SystemEntryID == null)
{
this.Session.SaveOrUpdate(iEntity);
}
else
{
throw new InvalidOperationException("Can't delete System Entries");
}
}
}
}
lTransaction.Commit();
}
catch (Exception e)
{
lTransaction.Rollback();
throw e;
}
}
lTransaction.Commit();
}
catch (Exception e)
{
lTransaction.Rollback();
throw e;
}
}
public virtual IList<T> GetAll<T>() where T : BeWoEntityBase
{
return this.CreateCriteria<T>().List<T>();
}
public virtual void Delete(BeWoEntityBase pEntity)
{
Debug.WriteLine($"---->DELETE von {pEntity.GetType().FullName}");
public virtual IList<T> GetAllActive<T>() where T : BeWoEntityBase
{
return this.GetAllWithActivationType<T>(ActivationTypeId.Active);
}
if (pEntity.SystemEntryID is null)
{
LogSignatureDeletion(pEntity);
public virtual IList<T> GetAllActiveAndArchived<T>() where T : BeWoEntityBase
{
return this.CreateCriteria<T>().Add(Restrictions.Or(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active), Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Archived))).List<T>();
}
var lTransaction = Session.BeginTransaction();
public virtual IList<T> GetAllWithActivationType<T>(ActivationTypeId activationType) where T : BeWoEntityBase
{
try
{
Session.Delete(pEntity);
lTransaction.Commit();
}
catch (Exception e)
{
lTransaction.Rollback();
throw e;
}
}
else
{
throw new InvalidOperationException("Can't delete System Entries");
}
}
public virtual void Delete<T>(IEnumerable<T> pEntitys) where T : BeWoEntityBase, new()
{
if (pEntitys?.FirstOrDefault() is object obj)
{
Debug.WriteLine($"---->DELETE von {obj.GetType().FullName}");
}
var entities = pEntitys.ToList();
foreach (var entity in entities)
{
LogSignatureDeletion(entity);
}
var lTransaction = Session.BeginTransaction();
try
{
foreach (var iEntity in entities)
{
if (iEntity.SystemEntryID is null || iEntity.SystemEntryID.Value == SystemEntryID.AdditionalServiceAssessmentSheet)
{
Session.Delete(iEntity);
}
else
{
throw new InvalidOperationException("Can't delete System Entries");
}
}
lTransaction.Commit();
}
catch (Exception e)
{
lTransaction.Rollback();
throw e;
}
}
public virtual IList<T> GetAll<T>() where T : BeWoEntityBase
{
return this.CreateCriteria<T>().List<T>();
}
public virtual IList<T> GetAllActive<T>() where T : BeWoEntityBase
{
return this.GetAllWithActivationType<T>(ActivationTypeId.Active);
}
public virtual IList<T> GetAllActiveAndArchived<T>() where T : BeWoEntityBase
{
return this.CreateCriteria<T>().Add(Restrictions.Or(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active), Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Archived))).List<T>();
}
public virtual IList<T> GetAllWithActivationType<T>(ActivationTypeId activationType) where T : BeWoEntityBase
{
return this.CreateCriteria<T>().Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, activationType)).List<T>();
}
}
public virtual T GetByID<T>(long pOid) where T : BeWoEntityBase, new()
{
return this.Session.Get<T>(pOid);
}
public virtual T GetByID<T>(long pOid) where T : BeWoEntityBase, new()
{
return this.Session.Get<T>(pOid);
}
public virtual List<T> GetByIDs<T>(IEnumerable<long> pOids) where T : BeWoEntityBase, new()
{
@@ -156,307 +156,330 @@ namespace BeWo.Data.Access
}
public virtual IList<T> GetActiveByIDs<T>(IEnumerable<long> pOids) where T : BeWoEntityBase, new()
{
return CreateCriteria<T>().Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active)).Add(Restrictions.In(BeWoEntityBase.PropertyName_Oid, pOids.ToArray())).List<T>();
}
{
return CreateCriteria<T>().Add(Restrictions.Eq(BeWoEntityBase.PropertyName_IsActive, ActivationTypeId.Active)).Add(Restrictions.In(BeWoEntityBase.PropertyName_Oid, pOids.ToArray())).List<T>();
}
public virtual void Insert(BeWoEntityBase pEntity)
{
var entityType = pEntity.GetType();
public virtual void Insert(BeWoEntityBase pEntity)
{
var entityType = pEntity.GetType();
Debug.WriteLine($"++++>INSERT von {entityType.FullName}");
Debug.WriteLine($"++++>INSERT von {entityType.FullName}");
if (pEntity is LightEntity)
throw new InvalidOperationException("Cannot insert LightEntity, only update! str:" + pEntity.ToString());
var session = Session;
if (session is null)
{
throw new InvalidOperationException("GenericDAO.Insert(): Session is null");
}
var lTransaction = session.BeginTransaction();
try
{
var session = Session;
{
pEntity.IsActive = ActivationTypeId.Active;
session.Save(pEntity);
lTransaction.Commit();
if(session is null)
{
throw new InvalidOperationException("GenericDAO.Insert(): Session is null");
}
if (pEntity is Signature signature)
{
LogSignatureInsert(signature);
}
}
catch (Exception e)
{
lTransaction.Rollback();
throw e;
}
}
var lTransaction = session.BeginTransaction();
try
{
pEntity.IsActive = ActivationTypeId.Active;
session.Save(pEntity);
lTransaction.Commit();
public virtual void Insert<T>(IEnumerable<T> pEntitys) where T : BeWoEntityBase, new()
{
if (pEntitys?.FirstOrDefault() is object obj)
{
Debug.WriteLine($"++++>INSERT von {obj.GetType().FullName}");
}
if(pEntity is Signature signature)
{
LogSignatureInsert(signature);
}
}
catch (Exception e)
{
lTransaction.Rollback();
throw e;
}
}
catch (Exception ex)
{
throw ex;
}
}
public virtual void Insert<T>(IEnumerable<T> pEntitys) where T : BeWoEntityBase, new()
{
if(pEntitys?.FirstOrDefault() is object obj)
{
Debug.WriteLine($"++++>INSERT von {obj.GetType().FullName}");
}
ITransaction lTransaction = this.Session.BeginTransaction();
try
{
foreach (BeWoEntityBase iEntity in pEntitys)
{
ITransaction lTransaction = this.Session.BeginTransaction();
try
{
foreach (BeWoEntityBase iEntity in pEntitys)
{
if (iEntity is LightEntity)
throw new InvalidOperationException("Cannot insert LightEntity, only update! str:" + iEntity.ToString());
this.Session.Save(iEntity);
}
}
lTransaction.Commit();
}
catch (Exception e)
{
lTransaction.Rollback();
throw e;
}
}
public virtual T LoadByID<T>(long pOid) where T : BeWoEntityBase, new()
{
return this.Session.Load<T>(pOid);
}
public virtual List<T> LoadByIDs<T>(IEnumerable<long> pOids) where T : BeWoEntityBase, new()
{
return pOids.Select(oid => this.LoadByID<T>(oid)).ToList();
}
public virtual T LoadSystemEntry<T>(SystemEntryID pId) where T : BeWoEntityBase, new()
{
return this.CreateCriteria<T>().Add(Restrictions.Eq(BeWoEntityBase.PropertyName_SystemEntryID, pId)).UniqueResult<T>();
}
public void Reattach<T>(T entity) where T : BeWoEntityBase, new()
{
this.Session.Lock(entity, LockMode.None);
}
public virtual void SetActivationType(BeWoEntityBase pEntity, ActivationTypeId activationType)
{
if (pEntity.SystemEntryID == null)
{
ITransaction lTransaction = this.Session.BeginTransaction();
try
{
pEntity.IsActive = activationType;
this.Session.SaveOrUpdate(pEntity);
lTransaction.Commit();
}
catch (Exception e)
{
lTransaction.Rollback();
throw e;
}
}
else
{
throw new InvalidOperationException("Can't delete System Entries");
}
}
public virtual void Update(BeWoEntityBase pEntity)
{
Debug.WriteLine($"####>UPDATE von {pEntity.GetType().FullName}");
if(pEntity is ServiceRecord serviceRecord && serviceRecord.Oid.HasValue)
{
var hasPreviouslyExistingSignature = DAOFactory.SearchDAO.CheckForExistingServiceRecordSignature(serviceRecord.Oid.Value);
if(hasPreviouslyExistingSignature && serviceRecord.SignatureOid is null)
{
LogSignatureDeletion(serviceRecord);
}
}
if(pEntity is Bargeldkasse bargeldkasse && bargeldkasse.Oid.HasValue)
{
var oldTransactions = DAOFactory.SearchDAO.LoadBargeldTransaktionenNonLazy(bargeldkasse.Oid.Value);
var deletedTransactions = oldTransactions.Where(oldTransaction => false == bargeldkasse.Bargeldtransaktionen.Any(x => x.Oid.HasValue && x.Oid.Equals(oldTransaction.Oid))).ToList();
var deletedTransactionsWithSignature = deletedTransactions.Where(oldTransaction => oldTransaction.SignatureOid.HasValue).ToList();
foreach(var deletedTransactionWithSignature in deletedTransactionsWithSignature)
{
LogSignatureDeletion(deletedTransactionWithSignature);
}
}
ITransaction lTransaction = this.Session.BeginTransaction();
try
{
this.Session.SaveOrUpdate(pEntity);
lTransaction.Commit();
}
catch (Exception e)
{
lTransaction.Rollback();
throw e;
}
}
public virtual void Update<T>(IEnumerable<T> pEntities) where T : BeWoEntityBase, new()
{
if(pEntities?.FirstOrDefault() is object obj)
{
Debug.WriteLine($"####>UPDATE von {obj.GetType().FullName}");
}
ITransaction lTransaction = this.Session.BeginTransaction();
try
{
if(pEntities is IEnumerable<ServiceRecord> serviceRecords)
{
foreach(var serviceRecord in serviceRecords)
{
if(serviceRecord.Oid is null)
{
continue;
}
var hasPreviouslyExistingSignature = DAOFactory.SearchDAO.CheckForExistingServiceRecordSignature(serviceRecord.Oid.Value);
if(hasPreviouslyExistingSignature && serviceRecord.SignatureOid is null)
{
LogSignatureDeletion(serviceRecord);
}
}
}
if(pEntities is IEnumerable<Bargeldkasse> bargeldkassen)
{
foreach(var bargeldkasse in bargeldkassen)
{
if(bargeldkasse.Oid is null)
{
continue;
}
var oldTransactions = DAOFactory.SearchDAO.LoadBargeldTransaktionenNonLazy(bargeldkasse.Oid.Value);
var deletedTransactions = oldTransactions.Where(oldTransaction => bargeldkasse.Bargeldtransaktionen.Any(x => x.Oid.HasValue && x.Oid.Equals(oldTransaction.Oid))).ToList();
var deletedTransactionsWithSignature = deletedTransactions.Where(oldTransaction => oldTransaction.SignatureOid.HasValue).ToList();
foreach(var deletedTransactionWithSignature in deletedTransactionsWithSignature)
{
LogSignatureDeletion(deletedTransactionWithSignature);
}
}
}
foreach (BeWoEntityBase iEntity in pEntities)
{
this.Session.SaveOrUpdate(iEntity);
}
lTransaction.Commit();
}
catch (Exception e)
{
lTransaction.Rollback();
throw e;
}
}
public virtual T Unproxy<T>(T obj)
{
if (!NHibernateUtil.IsInitialized(obj))
{
NHibernateUtil.Initialize(obj);
}
if (obj is INHibernateProxy)
{
return (T)this.Session.GetSessionImplementation().PersistenceContext.Unproxy(obj);
}
return obj;
}
public virtual int GetRowCount<T>() where T : BeWoEntityBase
{
return Session.QueryOver<T>().RowCount();
lTransaction.Commit();
}
catch (Exception e)
{
lTransaction.Rollback();
throw e;
}
}
private static void LogSignatureDeletion(BeWoEntityBase entity)
{
var signatureHistoryEntries = new List<SignatureHistory>();
public virtual T LoadByID<T>(long pOid) where T : BeWoEntityBase, new()
{
return this.Session.Load<T>(pOid);
}
switch(entity)
{
case Signature signature:
signatureHistoryEntries.AddIfNotNull(DAOFactory.SearchDAO.CreateSignatureHistoryEntry(signature, SignatureEventType.Delete));
break;
case ConfirmationReceiptSignature confirmationReceiptSignature:
signatureHistoryEntries.AddIfNotNull(DAOFactory.SearchDAO.CreateMonthlySignatureHistoryEntry(confirmationReceiptSignature, SignatureEventType.Delete));
break;
case ServiceRecord serviceRecord when serviceRecord.Oid.HasValue:
{
var s = DAOFactory.SearchDAO.LoadJustDeletedSignature(serviceRecord.Oid.Value, true);
public virtual List<T> LoadByIDs<T>(IEnumerable<long> pOids) where T : BeWoEntityBase, new()
{
return pOids.Select(oid => this.LoadByID<T>(oid)).ToList();
}
var signatureHistoryEntry = DAOFactory.SearchDAO.CreateSignatureHistoryEntry(s, SignatureEventType.CascadingDelete);
public virtual T LoadSystemEntry<T>(SystemEntryID pId) where T : BeWoEntityBase, new()
{
return this.CreateCriteria<T>().Add(Restrictions.Eq(BeWoEntityBase.PropertyName_SystemEntryID, pId)).UniqueResult<T>();
}
signatureHistoryEntries.AddIfNotNull(signatureHistoryEntry);
break;
}
case Bargeldkasse bargeldkasse when bargeldkasse.Bargeldtransaktionen.Any(bargeldtransaktion => bargeldtransaktion.SignatureOid.HasValue):
signatureHistoryEntries.AddRangeIfNotNull(DAOFactory.SearchDAO.CreateSignatureHistoryEntryForBargeldkasse(bargeldkasse));
break;
case Bargeldtransaktion bargeldtransaktion when bargeldtransaktion.SignatureOid.HasValue:
signatureHistoryEntries.AddIfNotNull(DAOFactory.SearchDAO.CreateSignatureHistoryForBargeldtransaktion(bargeldtransaktion, SignatureEventType.CascadingDelete));
break;
}
public void Reattach<T>(T entity) where T : BeWoEntityBase, new()
{
this.Session.Lock(entity, LockMode.None);
}
if(signatureHistoryEntries.Any())
{
DAOFactory.GenericDAO.Insert(signatureHistoryEntries.Where(she => she is object));
}
}
public virtual void SetActivationType(BeWoEntityBase pEntity, ActivationTypeId activationType)
{
if (pEntity.SystemEntryID == null)
{
ITransaction lTransaction = this.Session.BeginTransaction();
try
{
pEntity.IsActive = activationType;
this.Session.SaveOrUpdate(pEntity);
lTransaction.Commit();
}
catch (Exception e)
{
lTransaction.Rollback();
throw e;
}
}
else
{
throw new InvalidOperationException("Can't delete System Entries");
}
}
private static void LogSignatureUpdateForServiceRecord(ServiceRecord serviceRecord)
{
/*
public virtual void Update(BeWoEntityBase pEntity)
{
Debug.WriteLine($"####>UPDATE von {pEntity.GetType().FullName}");
if (pEntity is ServiceRecord serviceRecord && serviceRecord.Oid.HasValue)
{
var hasPreviouslyExistingSignature = DAOFactory.SearchDAO.CheckForExistingServiceRecordSignature(serviceRecord.Oid.Value);
if (hasPreviouslyExistingSignature && serviceRecord.SignatureOid is null)
{
LogSignatureDeletion(serviceRecord);
}
}
if (pEntity is Bargeldkasse bargeldkasse && bargeldkasse.Oid.HasValue)
{
var oldTransactions = DAOFactory.SearchDAO.LoadBargeldTransaktionenNonLazy(bargeldkasse.Oid.Value);
var deletedTransactions = oldTransactions.Where(oldTransaction => false == bargeldkasse.Bargeldtransaktionen.Any(x => x.Oid.HasValue && x.Oid.Equals(oldTransaction.Oid))).ToList();
var deletedTransactionsWithSignature = deletedTransactions.Where(oldTransaction => oldTransaction.SignatureOid.HasValue).ToList();
foreach (var deletedTransactionWithSignature in deletedTransactionsWithSignature)
{
LogSignatureDeletion(deletedTransactionWithSignature);
}
}
ITransaction lTransaction = this.Session.BeginTransaction();
try
{
this.Session.SaveOrUpdate(pEntity);
lTransaction.Commit();
}
catch (Exception e)
{
lTransaction.Rollback();
throw e;
}
}
public virtual void Update<T>(IEnumerable<T> pEntities) where T : BeWoEntityBase, new()
{
if (pEntities?.FirstOrDefault() is object obj)
{
Debug.WriteLine($"####>UPDATE von {obj.GetType().FullName}");
}
ITransaction lTransaction = this.Session.BeginTransaction();
try
{
if (pEntities is IEnumerable<ServiceRecord> serviceRecords)
{
foreach (var serviceRecord in serviceRecords)
{
if (serviceRecord.Oid is null)
{
continue;
}
var hasPreviouslyExistingSignature = DAOFactory.SearchDAO.CheckForExistingServiceRecordSignature(serviceRecord.Oid.Value);
if (hasPreviouslyExistingSignature && serviceRecord.SignatureOid is null)
{
LogSignatureDeletion(serviceRecord);
}
}
}
if (pEntities is IEnumerable<Bargeldkasse> bargeldkassen)
{
foreach (var bargeldkasse in bargeldkassen)
{
if (bargeldkasse.Oid is null)
{
continue;
}
var oldTransactions = DAOFactory.SearchDAO.LoadBargeldTransaktionenNonLazy(bargeldkasse.Oid.Value);
var deletedTransactions = oldTransactions.Where(oldTransaction => bargeldkasse.Bargeldtransaktionen.Any(x => x.Oid.HasValue && x.Oid.Equals(oldTransaction.Oid))).ToList();
var deletedTransactionsWithSignature = deletedTransactions.Where(oldTransaction => oldTransaction.SignatureOid.HasValue).ToList();
foreach (var deletedTransactionWithSignature in deletedTransactionsWithSignature)
{
LogSignatureDeletion(deletedTransactionWithSignature);
}
}
}
foreach (BeWoEntityBase iEntity in pEntities)
{
this.Session.SaveOrUpdate(iEntity);
}
lTransaction.Commit();
}
catch (Exception e)
{
lTransaction.Rollback();
throw e;
}
}
public virtual T Unproxy<T>(T obj)
{
if (!NHibernateUtil.IsInitialized(obj))
{
NHibernateUtil.Initialize(obj);
}
if (obj is INHibernateProxy)
{
return (T)this.Session.GetSessionImplementation().PersistenceContext.Unproxy(obj);
}
return obj;
}
public virtual int GetRowCount<T>() where T : BeWoEntityBase
{
return Session.QueryOver<T>().RowCount();
}
public virtual int GetRowCount<T>(string pPropertyName, object value) where T : BeWoEntityBase
{
var count = CreateCriteria<T>()
.Add(Restrictions.Eq(pPropertyName, value))
.SetProjection(Projections.RowCount())
.UniqueResult<int>();
return count;
}
public virtual bool Any<T>() where T : BeWoEntityBase
{
return GetRowCount<T>() > 0;
}
public virtual bool Any<T>(string pPropertyName, object value) where T : BeWoEntityBase
{
return GetRowCount<T>(pPropertyName, value) > 0;
}
public virtual bool Exists<T>(string pPropertyName, object value) where T : BeWoEntityBase
{
return GetRowCount<T>(pPropertyName, value) > 0;
}
public T GetByProperty<T>(string pPropertyName, object value) where T : BeWoEntityBase
{
return CreateCriteria<T>().Add(Restrictions.Eq(pPropertyName, value)).UniqueResult<T>();
}
private static void LogSignatureDeletion(BeWoEntityBase entity)
{
var signatureHistoryEntries = new List<SignatureHistory>();
switch (entity)
{
case Signature signature:
signatureHistoryEntries.AddIfNotNull(DAOFactory.SearchDAO.CreateSignatureHistoryEntry(signature, SignatureEventType.Delete));
break;
case ConfirmationReceiptSignature confirmationReceiptSignature:
signatureHistoryEntries.AddIfNotNull(DAOFactory.SearchDAO.CreateMonthlySignatureHistoryEntry(confirmationReceiptSignature, SignatureEventType.Delete));
break;
case ServiceRecord serviceRecord when serviceRecord.Oid.HasValue:
{
var s = DAOFactory.SearchDAO.LoadJustDeletedSignature(serviceRecord.Oid.Value, true);
var signatureHistoryEntry = DAOFactory.SearchDAO.CreateSignatureHistoryEntry(s, SignatureEventType.CascadingDelete);
signatureHistoryEntries.AddIfNotNull(signatureHistoryEntry);
break;
}
case Bargeldkasse bargeldkasse when bargeldkasse.Bargeldtransaktionen.Any(bargeldtransaktion => bargeldtransaktion.SignatureOid.HasValue):
signatureHistoryEntries.AddRangeIfNotNull(DAOFactory.SearchDAO.CreateSignatureHistoryEntryForBargeldkasse(bargeldkasse));
break;
case Bargeldtransaktion bargeldtransaktion when bargeldtransaktion.SignatureOid.HasValue:
signatureHistoryEntries.AddIfNotNull(DAOFactory.SearchDAO.CreateSignatureHistoryForBargeldtransaktion(bargeldtransaktion, SignatureEventType.CascadingDelete));
break;
}
if (signatureHistoryEntries.Any())
{
DAOFactory.GenericDAO.Insert(signatureHistoryEntries.Where(she => she is object));
}
}
private static void LogSignatureUpdateForServiceRecord(ServiceRecord serviceRecord)
{
/*
* Wird bei folgenden Szenarien ausgeführt:
*
* 1. Direkt nach dem Signature-Insert (Erst das Signature-Insert, dann das ServiceRecord-Update, um die SignatureOid in die ServiceRecord-Tabelle zu schreiben).
* 2. Beim Löschen der Signature
*/
var hasPreviouslyExistingSignature = DAOFactory.SearchDAO.CheckForExistingServiceRecordSignature(serviceRecord.Oid.Value);
var hasPreviouslyExistingSignature = DAOFactory.SearchDAO.CheckForExistingServiceRecordSignature(serviceRecord.Oid.Value);
// Prüfen, ob es sich um ein Update, ausgelöst durch das Insert der Unterschrift, handelt.
if(false == hasPreviouslyExistingSignature)
{
return;
}
// Prüfen, ob es sich um ein Update, ausgelöst durch das Insert der Unterschrift, handelt.
if (false == hasPreviouslyExistingSignature)
{
return;
}
var signatureHistory = DAOFactory.SearchDAO.CreateSignatureHistoryForServiceRecordUpdate(serviceRecord, SignatureEventType.CascadingDelete);
DAOFactory.GenericDAO.Insert(signatureHistory);
}
var signatureHistory = DAOFactory.SearchDAO.CreateSignatureHistoryForServiceRecordUpdate(serviceRecord, SignatureEventType.CascadingDelete);
DAOFactory.GenericDAO.Insert(signatureHistory);
}
private static void LogSignatureInsert(Signature signature)
{
var signatureHistory = DAOFactory.SearchDAO.CreateSignatureHistoryEntry(signature, SignatureEventType.Insert);
DAOFactory.GenericDAO.Insert(signatureHistory);
}
}
private static void LogSignatureInsert(Signature signature)
{
var signatureHistory = DAOFactory.SearchDAO.CreateSignatureHistoryEntry(signature, SignatureEventType.Insert);
DAOFactory.GenericDAO.Insert(signatureHistory);
}
}
}

View File

@@ -32,21 +32,14 @@ namespace BeWo.Data.Access
return Path.Combine(_rootPath, filePath);
}
public async Task SaveLogAsync(string pFileName, Stream content, CancellationToken cancellationToken = default)
{
var lFilePath = Path.Combine("logs", pFileName);
await SaveFileAsync(lFilePath, pFileName, content, cancellationToken).ConfigureAwait(true);
}
private async Task SaveFileAsync(string pFilePath, string pFileName, Stream content, CancellationToken cancellationToken = default)
{
// Prüfe Namen
if (SecurityUtils.ContainsInvalidFilenameChars(pFileName))
throw new BeWoInvalidOperationException(AppError.LocalFileStorageFileNameInvalidChar);
throw new BeWoInvalidOperationException(AppError.FileNameInvalidChar);
if (Path.GetFileName(pFilePath) != pFileName)
throw new BeWoInvalidOperationException(AppError.LocalFileStorageFileNameNotEqFilePath);
throw new BeWoInvalidOperationException(AppError.FileNameNotEqFilePath);
// Erstelle File Ordner
var path = GetFilePath(pFilePath);

View File

@@ -3,6 +3,7 @@ using BS.Shared;
using BS.Shared.Core;
using BS.Shared.Exceptions;
using BS.Shared.Interface;
using DevExpress.DataAccess.Native.Web;
using System;
using System.Collections.Generic;
using System.IO;
@@ -19,6 +20,8 @@ namespace BeWo.Data.Access
{
public class LocalTenantFileStorageDAO
{
public string Tenant => MultitenancyOperationContextExt.Current?.Tenant ?? throw new BeWoInvalidOperationException(AppError.MultitenancyOperationTenantUnknown);
private readonly string _rootPath;
public LocalTenantFileStorageDAO(string rootPath)
@@ -26,47 +29,54 @@ namespace BeWo.Data.Access
_rootPath = rootPath;
}
private string GetFilePath(string tenant, string filePath)
public string GetXRechnungFileName(long invoicebase_oid)
{
return Path.Combine(_rootPath, tenant, filePath);
return $"invoicebase_{invoicebase_oid}_xrechnung.pdf";
}
private string GetFilePath(string filePath)
{
return Path.Combine(_rootPath, Tenant, filePath);
}
public async Task<IStoredFile> SaveXRechnungPdfAsync(string tenant, IInvoiceBase invoicebase, Stream content)
{
var lTid = (int)TableID.InvoiceBase;
var lOid = invoicebase.Oid;
var lFileName = $"{lOid}.XRechnung.pdf";
return await SaveFileAsync(tenant, BWPFeature.XRechnung, lFileName, "application/pdf", content, lTid, lOid).ConfigureAwait(true);
}
private async Task<IStoredFile> SaveFileAsync(string tenant, BWPFeature feature, string pFileName, string pContentType, Stream content, int? pBeWoObjectTid = null, long? pBeWoObjectOid = null, CancellationToken cancellationToken = default)
{
var lFilePath = feature.ToString();
return await SaveFileAsync(tenant, lFilePath, pFileName, pContentType, content, pBeWoObjectTid, pBeWoObjectOid, cancellationToken).ConfigureAwait(true);
}
private async Task<IStoredFile> SaveFileAsync(string tenant, string pFilePath, string pFileName, string pContentType, Stream content, int? pBeWoObjectTid = null, long? pBeWoObjectOid = null, CancellationToken cancellationToken = default)
public StoredFile SaveHybridFile(BWPFeature feature, string pFileName, string pContentType, Stream content,
int? pBeWoObjectTid = null, long? pBeWoObjectOid = null, CancellationToken cancellationToken = default)
{
// Prüfe Namen
if (SecurityUtils.ContainsInvalidFilenameChars(pFilePath))
throw new BeWoInvalidOperationException(AppError.LocalFileStorageFileNameInvalidChar);
if (SecurityUtils.ContainsInvalidFilenameChars(pFileName))
throw new BeWoInvalidOperationException(AppError.FileNameInvalidChar);
if (Path.GetFileName(pFilePath) != pFileName)
throw new BeWoInvalidOperationException(AppError.LocalFileStorageFileNameNotEqFilePath);
var lFilePath = Path.Combine(feature.ToString(), pFileName);
// Prüfe Path
if (Path.GetFileName(lFilePath) != pFileName)
throw new BeWoInvalidOperationException(AppError.FileNameNotEqFilePath);
// Prüfe Doppelte Belegung
if (DAOFactory.GenericDAO.Exists<StoredFile>(nameof(StoredFile.FilePath), lFilePath))
throw new BeWoInvalidOperationException(AppError.StoredFileAlreadyExists);
// Erstelle DB Eintrag
var storedfile = new StoredFile();
storedfile.FileName = pFileName;
storedfile.FilePath = pFilePath;
storedfile.FilePath = lFilePath;
storedfile.ContentType = pContentType;
storedfile.BeWoObjectTid = pBeWoObjectTid;
storedfile.BeWoObjectOid = pBeWoObjectOid;
// Speichere FileAsync
storedfile = SaveFileAsync(storedfile, content, cancellationToken).GetAwaiter().GetResult();
// Speichere DB Eintrag
DAOFactory.GenericDAO.Insert(storedfile);
return storedfile;
}
private async Task<StoredFile> SaveFileAsync(StoredFile storedFile, Stream content, CancellationToken cancellationToken = default)
{
// Erstelle File Ordner
var path = GetFilePath(tenant, pFilePath);
var path = GetFilePath(storedFile.FilePath);
var directory = Path.GetDirectoryName(path);
Directory.CreateDirectory(directory);
@@ -74,38 +84,46 @@ namespace BeWo.Data.Access
using (var stream = File.Create(path))
{
await content.CopyToAsync(stream, bufferSize: 81920, cancellationToken).ConfigureAwait(true);
storedfile.Size = content.Position;
storedfile.Checksum = SecurityUtils.GetChecksumBuffered(content);
storedFile.Size = content.Position;
storedFile.Checksum = SecurityUtils.GetChecksumBuffered(content);
}
return storedfile;
return storedFile;
}
public Task<bool> FileExistsAsync(string tenant, IStoredFile storedFile, CancellationToken cancellationToken = default)
public IStoredFile GetFileInfo(BWPFeature feature, string pFileName)
{
return Task.FromResult(File.Exists(GetFilePath(tenant, storedFile.FilePath)));
var lFilePath = Path.Combine(feature.ToString(), pFileName);
return GetFileInfo(lFilePath);
}
public IStoredFile GetFileInfo(string filePath)
{
var file = DAOFactory.GenericDAO.GetByProperty<StoredFile>(nameof(StoredFile.FilePath), filePath);
return file;
}
public Task<Stream> GetFileAsync(string tenant, IStoredFile storedFile, CancellationToken cancellationToken = default)
public Stream GetFileContent(IStoredFile storedFile, CancellationToken cancellationToken = default)
{
var path = GetFilePath(tenant, storedFile.FilePath);
var path = GetFilePath(storedFile.FilePath);
if (!File.Exists(path))
return Task.FromResult<Stream>(null);
return null;
Stream stream = File.OpenRead(path);
return Task.FromResult(stream);
return stream;
}
public Task<bool> DeleteFileAsync(string tenant, IStoredFile storedFile, CancellationToken cancellationToken = default)
public bool DeleteFile(IStoredFile storedFile, CancellationToken cancellationToken = default)
{
var path = GetFilePath(tenant, storedFile.FilePath);
var path = GetFilePath(storedFile.FilePath);
if (File.Exists(path))
{
File.Delete(path);
return Task.FromResult(true);
return true;
}
return Task.FromResult(false);
return false;
}
}
}

View File

@@ -1,25 +1,27 @@
using System.ServiceModel;
using BS.Shared.Core;
using BS.Shared.Exceptions;
using System.ServiceModel;
namespace BeWo.Data
{
public class MultitenancyOperationContextExt : IExtension<OperationContext>
{
public static MultitenancyOperationContextExt Current
{
get
{
public class MultitenancyOperationContextExt : IExtension<OperationContext>
{
public static MultitenancyOperationContextExt Current
{
get
{
return OperationContext.Current != null ? OperationContext.Current.Extensions.Find<MultitenancyOperationContextExt>() : null;
}
}
}
}
public string Tenant { get; set; }
public string Tenant { get; set; }
public void Attach(OperationContext owner)
{
}
public void Attach(OperationContext owner)
{
}
public void Detach(OperationContext owner)
{
}
}
public void Detach(OperationContext owner)
{
}
}
}

View File

@@ -13,6 +13,8 @@ using log4net;
using log4net.Appender;
using log4net.Layout;
using log4net.Repository.Hierarchy;
using BS.Shared.Exceptions;
using BS.Shared.Core;
namespace BeWo.Data
{
@@ -28,7 +30,7 @@ namespace BeWo.Data
{
get
{
return SessionOperationContextExt.Current == null ? null : SessionOperationContextExt.Current.Session;
return SessionOperationContextExt.Current?.Session;
}
private set
@@ -116,9 +118,10 @@ namespace BeWo.Data
fact.Dispose();
}
catch (Exception)
catch (Exception e)
{
//ignore exception??
throw e;
}
@@ -149,7 +152,7 @@ namespace BeWo.Data
{
if (!TenantExists())
{
return null;
throw new BeWoInvalidOperationException(AppError.MultitenancyOperationTenantUnknown);
}
Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
//System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
@@ -170,7 +173,7 @@ namespace BeWo.Data
{
File.AppendAllText(Path.Combine(_LogsDirectory, "WCFSessionError.txt"), $"OpenSession {DateTime.Now:dd.MM.yyyy HH:mm:ss}" + "\n" + e.Message + "\n" + e.StackTrace);
}
throw new FaultException(e.StackTrace + e.InnerException?.Message);
}
}

View File

@@ -3,7 +3,7 @@
<PropertyGroup>
<NameOfLastUsedPublishProfile>C:\Projects\Bewo\BeWo - Main\Host\Properties\PublishProfiles\FolderProfile.pubxml</NameOfLastUsedPublishProfile>
<UseIISExpress>true</UseIISExpress>
<LastActiveSolutionConfig>Release|Any CPU</LastActiveSolutionConfig>
<LastActiveSolutionConfig>Debug|Any CPU</LastActiveSolutionConfig>
<Use64BitIISExpress>false</Use64BitIISExpress>
<IISExpressSSLPort />
<IISExpressAnonymousAuthentication />

View File

@@ -323,5 +323,7 @@
<add key="StoredTenantFilesFolderPath" value="C:\BeWoPlaner\StoredTenantFiles"/>
<add key="StoredFilesFolderPath" value="C:\BeWoPlaner\StoredFiles"/>
<add key="HelloWorldPdfLocation" value="C:\BeWoPlaner\StoredFiles\HelloWorld.pdf"/>
<add key="ServiceLogFilePath" value="C:\StoredFiles\logs\server\service.log.txt"/>
</appSettings>
</configuration>

View File

@@ -394,7 +394,9 @@
<add key="XRechnungApiUrl" value="https://test2.evplaner.de/xrg/"/>
<add key="StoredFilesFolderPath" value="C:\StoredFiles"/>
<add key="StoredTenantFilesFolderPath" value="C:\StoredTenantFiles"/>
<add key="HelloWorldPdfLocation" value="C:\StoredFiles\HelloWorld.pdf"/>
<add key="HelloWorldPdfLocation" value="C:\StoredFiles\HelloWorld.pdf"/>
<add key="ServiceLogFilePath" value="C:\StoredFiles\logs\server\service.log.txt"/>
</appSettings>
<!-- <> <> <> Appsettings <> <> <> -->
</configuration>

View File

@@ -12,7 +12,8 @@ namespace BeWo.Service
XRechnungApiUrl,
StoredFilesFolderPath,
StoredTenantFilesFolderPath,
HelloWorldPdfLocation
HelloWorldPdfLocation,
ServiceLogFilePath
}
public enum WebSecretConfigSetting

View File

@@ -0,0 +1,47 @@
using BS.Shared;
using BS.Shared.Core;
using BS.Shared.Exceptions;
using BS.Shared.Interface;
using RestSharp.Validation;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BeWo.Service.Core
{
public class FileLogger
{
private readonly string _filePath;
private readonly LogLevel _minimumLevel;
private readonly object _lock = new object();
public FileLogger(string filePath, LogLevel minimumLevel = LogLevel.Debug)
{
if(filePath == null) throw new ArgumentNullException(nameof(filePath));
if(!File.Exists(filePath)) throw new BeWoInvalidOperationException(AppError.LoggerFileDoNotExist);
_filePath = filePath;
_minimumLevel = minimumLevel;
}
public void LogError(Exception exception, string module = null)
=> Log(LogLevel.Error, exception.ToString(), module);
public void Log(LogLevel level, string message, string module = null)
{
if (level < _minimumLevel)
return;
string timestamp = DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss,ff");
string logEntry = $"[{timestamp}] [{level}] {module}: {message}";
lock (_lock)
{
File.AppendAllText(_filePath, logEntry + Environment.NewLine);
}
}
}
}

View File

@@ -236,6 +236,7 @@
<Compile Include="Core\DiamantExporter.cs" />
<Compile Include="Core\ExcelDownload.cs" />
<Compile Include="Core\FileAttachmentUtils.cs" />
<Compile Include="Core\FileLogger.cs" />
<Compile Include="Core\MergedConfig.cs" />
<Compile Include="Core\ServiceLogic.cs" />
<Compile Include="Core\SettingsLogic.cs" />

View File

@@ -32,6 +32,8 @@ namespace BeWo.Service.ServiceBehavior.JsonError
{
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
ServiceHelper.CoreLogger.LogError(error, nameof(JsonErrorHandler));
// Erstelle eine JSON-Fehlermeldung
var jsonError = new JsonError
{
@@ -53,9 +55,6 @@ namespace BeWo.Service.ServiceBehavior.JsonError
serializer.WriteObject(stream, jsonError);
stream.Position = 0;
ServiceHelper.WriteLogFile("LastJsonError.json.txt", stream);
stream.Position = 0;
using (var reader = new StreamReader(stream))
{
string jsonString = reader.ReadToEnd();

View File

@@ -1,4 +1,5 @@
using BeWo.Service.Core;
using BeWo.Service.ServiceUtils;
using System;
using System.Collections.Generic;
using System.Configuration;
@@ -24,6 +25,8 @@ namespace BeWo.Service.ServiceBehavior.WCFError
public void ProvideFault(Exception error, MessageVersion version, ref Message message)
{
ServiceHelper.CoreLogger.LogError(error, nameof(WCFErrorHandler));
var wcfError = Utils.CreateBeWoFaultException(error);
var fault = wcfError.CreateMessageFault();

View File

@@ -4,6 +4,7 @@ using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Feature.AI;
using BS.Shared.DataContracts.Invoicing.XRechnung;
using BS.Shared.DataContracts.MikePHPContracts;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -18,6 +19,6 @@ namespace BeWo.Service.ServiceContracts.Enhanced
{
[FaultContract(typeof(BeWoFault))]
[OperationContract]
XRechnungResponse CreateXRechnung(long invoice_base_oid, int report_type, string report_url);
ApiResponse<byte[]> GetXRechnung(long invoice_base_oid, int report_type, string report_url);
}
}

View File

@@ -27,7 +27,7 @@ namespace BeWo.Service.ServiceImplementations
var identity = WindowsIdentity.GetCurrent();
var message = $"{identity.Name} - {identity.IsAuthenticated} - {identity.AuthenticationType}";
ServiceHelper.WriteLogFile("ApiServiceTest", message);
ServiceHelper.CoreLogger.Log(BS.Shared.LogLevel.Debug, message, $"{nameof(ApiServiceImp)}.{nameof(Test)}");
return ApiResponse<string>.SuccessResponse("Hello World!");
}

View File

@@ -3,6 +3,7 @@ using BeWo.Data.Access;
using BeWo.Data.Entities;
using BeWo.Data.Models.XRechnung;
using BeWo.Data.Security;
using BeWo.Service.Core;
using BeWo.Service.DCEntityMapper;
using BeWo.Service.ServiceContracts.Enhanced;
using BeWo.Service.ServiceProxy;
@@ -12,7 +13,9 @@ using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Feature.AI;
using BS.Shared.DataContracts.Invoicing.XRechnung;
using BS.Shared.DataContracts.MikePHPContracts;
using DevExpress.CodeParser;
using DevExpress.Entity.Model.Metadata;
using DevExpress.XtraRichEdit.Model;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
@@ -28,11 +31,23 @@ namespace BeWo.Service.ServiceImplementations.Enhanced
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)]
public class AccountingEnhancedServiceImp : IAccountingEnhancedService
{
public XRechnungResponse CreateXRechnung(long invoice_base_oid, int report_type, string report_url)
public ApiResponse<byte[]> GetXRechnung(long invoice_base_oid, int report_type, string report_url)
{
if (string.IsNullOrWhiteSpace(report_url))
throw new ArgumentNullException(nameof(report_url));
// Hole Parameter
var lStoragePath = MergedConfig.GetSetting(WebConfigSetting.StoredTenantFilesFolderPath);
var lStorage = DAOFactory.GetLocalTenantFileStorage(lStoragePath);
var lFileName = lStorage.GetXRechnungFileName(invoice_base_oid);
var lFile = lStorage.GetFileInfo(BWPFeature.XRechnung, lFileName);
if (lFile is object)
{
}
// Berechne XRechnung
var str = ServiceConfigReader.GetInvoiceTestJsonString();
@@ -42,6 +57,27 @@ namespace BeWo.Service.ServiceImplementations.Enhanced
var response = ServiceFacade.XRechnung.Create(str, token_url);
if (response.Success)
{
//try
//{
// var file = storage.SaveXRechnungPdf(tenant, invoice_base_oid, response.ResponseBytes);
// ServiceHelper.CoreLogger.Log(LogLevel.Info, $"Tenant: {tenant}, FilePath: {file.FilePath}", $"{nameof(LocalFileStorageDAO)}.{nameof(storage.SaveXRechnungPdf)}");
//}
//catch (Exception ex)
//{
// try
// {
// ServiceHelper.CoreLogger.LogError(ex, nameof(GetXRechnung));
// }
// catch(Exception ex2)
// {
// response.Errors.Add("AccountingEnhancedServiceImp: " + ex2.ToString());
// }
// response.Errors.Add("AccountingEnhancedServiceImp: " + ex.ToString());
//}
}
return response;
}
}

View File

@@ -5,6 +5,7 @@ using BS.Shared.Core;
using BS.Shared.Core.Facade;
using BS.Shared.DataContracts.Feature.AI;
using BS.Shared.DataContracts.Invoicing.XRechnung;
using BS.Shared.DataContracts.MikePHPContracts;
using DevExpress.XtraRichEdit.Model;
using Newtonsoft.Json;
using System;
@@ -27,7 +28,7 @@ namespace BeWo.Service.ServiceProxy
_JsonHttpClientFacade = new JsonHttpClientFacade(base_url);
}
public XRechnungResponse Create(object xrechnung)
public ApiResponse<byte[]> Create(object xrechnung)
{
_JsonHttpClientFacade.JsonObject = new
{
@@ -36,12 +37,12 @@ namespace BeWo.Service.ServiceProxy
var bytes = _JsonHttpClientFacade.SendAsync("create").GetAwaiter().GetResult();
var response = XRechnungResponse.Parse(bytes);
var response = ApiResponse<byte[]>.Parse(bytes);
return response;
}
public XRechnungResponse Create(object xrechnung, string url)
public ApiResponse<byte[]> Create(object xrechnung, string url)
{
_JsonHttpClientFacade.JsonObject = new
{
@@ -51,7 +52,7 @@ namespace BeWo.Service.ServiceProxy
var bytes = _JsonHttpClientFacade.SendAsync("create").GetAwaiter().GetResult();
var response = XRechnungResponse.Parse(bytes);
var response = ApiResponse<byte[]>.Parse(bytes);
return response;
}

View File

@@ -15,7 +15,7 @@ namespace BeWo.Service.ServiceUtils.DistanceCalculator
{
public class GoogleDistanceMatrixApi : IDistanceAPI
{
public class Response
public class GoogleDistanceMatrixResponse
{
public string Status { get; set; }
@@ -102,12 +102,12 @@ namespace BeWo.Service.ServiceUtils.DistanceCalculator
{
var content = await response.Content.ReadAsStringAsync();
return FillMatrix(JsonConvert.DeserializeObject<Response>(content));
return FillMatrix(JsonConvert.DeserializeObject<GoogleDistanceMatrixResponse>(content));
}
}
}
public AddressRouteMatrix FillMatrix(Response response)
public AddressRouteMatrix FillMatrix(GoogleDistanceMatrixResponse response)
{
for (int i = 0; i < response.Rows.Length; i++)
{
@@ -131,7 +131,7 @@ namespace BeWo.Service.ServiceUtils.DistanceCalculator
return Matrix;
}
public AddressRoute ToAddressRoute(Response.Element element)
public AddressRoute ToAddressRoute(GoogleDistanceMatrixResponse.Element element)
{
var res = new AddressRoute();

View File

@@ -10,8 +10,11 @@ using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.Text;
using System.Threading.Tasks;
using BeWo.Data;
using BeWo.Data.Access;
using BeWo.Service.Core;
using BS.Shared.Core;
using BS.Shared.Exceptions;
using BS.Shared.Extensions;
using NHibernate.Hql.Ast.ANTLR.Tree;
@@ -19,6 +22,8 @@ namespace BeWo.Service.ServiceUtils
{
public static class ServiceHelper
{
public static FileLogger CoreLogger { get; } = new FileLogger(MergedConfig.GetSetting(WebConfigSetting.ServiceLogFilePath));
public static Tuple<string, string> GetInterfaceAndMethodASP(Message request , IClientChannel channel)
{
// Hole Interface
@@ -112,34 +117,5 @@ namespace BeWo.Service.ServiceUtils
return attribute;
}
public static void WriteLogFile(string pFileName, string pContent, string root_path = null)
{
if (root_path == null)
root_path = MergedConfig.GetSetting(WebConfigSetting.StoredFilesFolderPath);
var storage = DAOFactory.GetLocalFileStorage(root_path);
using (var stream = new MemoryStream())
{
using (var writer = new StreamWriter(stream))
{
writer.Write(pContent);
writer.Flush();
stream.Position = 0;
storage.SaveLogAsync(pFileName, stream).GetAwaiter().GetResult();
}
}
}
public static void WriteLogFile(string pFileName, Stream pContent)
{
var root_path = MergedConfig.GetSetting(WebConfigSetting.StoredFilesFolderPath);
var storage = DAOFactory.GetLocalFileStorage(root_path);
storage.SaveLogAsync(pFileName, pContent).GetAwaiter().GetResult();
}
}
}

View File

@@ -4,6 +4,7 @@ using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using BeWo.Data;
using BeWo.Service.ServiceUtils;
namespace BeWo.Service.UnitOfWork
{

View File

@@ -1373,4 +1373,12 @@ namespace BS.Shared
GkvAbrechnung = 11,
AiConversation = 12,
}
public enum LogLevel
{
Debug,
Info,
Warning,
Error,
}
}

View File

@@ -32,9 +32,14 @@ namespace BS.Shared.Core
}
//public static readonly AppError Example = new AppError("Code", "Message");
public static AppError MultitenancyOperationTenantUnknown => new AppError("SERV.HLP.10001", "Tenant unbekannt");
public static readonly AppError LocalFileStorageFileNameInvalidChar = new AppError("DATA.LFS.60001", "Fehler beim Speichern");
public static readonly AppError LocalFileStorageFileNameNotEqFilePath = new AppError("DATA.LFS.60002", "Fehler beim Speichern");
public static readonly Func<OrganisationDC, AppError> GkvDatenannahmestelleAdresseNotFound = (dc) => new AppError("GKV.70001", $"Unbekannte Datenannahmestelle. Bitte neu in der Organisation {dc.Name} ermitteln");
public static AppError LoggerFileDoNotExist => new AppError("SERV.LOG.10001", "Server falsch konfiguriert");
public static AppError FileNameInvalidChar => new AppError("DATA.LFS.60001", "Fehler beim Speichern");
public static AppError FileNameNotEqFilePath => new AppError("DATA.LFS.60002", "Fehler beim Speichern");
public static AppError StoredFileAlreadyExists => new AppError("DATA.LFS.60003", "Fehler beim Speichern");
public static Func<OrganisationDC, AppError> GkvDatenannahmestelleAdresseNotFound => (dc) => new AppError("GKV.70001", $"Unbekannte Datenannahmestelle. Bitte neu in der Organisation {dc.Name} ermitteln");
}
}

View File

@@ -13,7 +13,7 @@ namespace BS.Shared.DataContracts.Invoicing.XRechnung
{
[DataMember] public byte[] ResponseBytes { get; set; }
[DataMember] public string ResponseString { get; set; }
[DataMember] public List<string> Errors { get; set; }
[DataMember] public List<string> Errors { get; set; } = new List<string>();
public bool HasErrors => Errors is object && Errors.Any();
@@ -70,5 +70,7 @@ namespace BS.Shared.DataContracts.Invoicing.XRechnung
}
}
public string ErrorString => string.Join(", ", Errors);
}
}

View File

@@ -1,4 +1,5 @@
using BS.Shared.Core;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -7,12 +8,14 @@ using System.Threading.Tasks;
namespace BS.Shared.DataContracts.MikePHPContracts
{
public class ApiResponse<T>
public class ApiResponse<T>
{
public T Data { get; set; }
public List<AppError> Errors { get; set; }
public List<string> ErrorStrings { get; set; }
public List<string> Messages { get; set; }
public Dictionary<string, object> Meta { get; set; }
@@ -23,7 +26,7 @@ namespace BS.Shared.DataContracts.MikePHPContracts
public int StatusCode { get; set; } = 200;
public bool Success => Errors.Count == 0;
public bool Success => (Errors?.Count ?? 0) == 0 && (ErrorStrings?.Count ?? 0) == 0;
//Factory Methods
public static ApiResponse<T> SuccessResponse(T data, List<string> messages = null, Dictionary<string, object> meta = null)
@@ -50,5 +53,54 @@ namespace BS.Shared.DataContracts.MikePHPContracts
{
return FailureResponse(new List<AppError> { error }, statusCode, traceId);
}
//Parse Methods
public static ApiResponse<T> Parse(object obj)
{
var response = new ApiResponse<T>();
if (typeof(T) == typeof(byte[]))
{
response.Data = (T)obj;
var response_string = Encoding.UTF8.GetString(obj as byte[]);
var kv = JsonConvert.DeserializeObject<Dictionary<string, List<string>>>(response_string);
if (kv is object && kv.TryGetValue("errors", out var errors))
{
response.ErrorStrings = errors;
}
}
else
{
throw new NotImplementedException("typeof(T) not implemented!");
}
return response;
}
public string ToErrorString()
{
var sb = new StringBuilder();
if (Errors is object && Errors.Any())
{
foreach (var appError in Errors)
{
sb.AppendLine(appError.Displayname);
}
}
if (ErrorStrings is object && ErrorStrings.Any())
{
foreach (var error in ErrorStrings)
{
sb.AppendLine(error);
}
}
return sb.ToString();
}
}
}