Merge branch 'master' of ssh://float.ownsoft.de/git/beyondSoft/BeWo

This commit is contained in:
2026-07-13 09:16:09 +02:00
12 changed files with 336 additions and 189 deletions

View File

@@ -49,10 +49,12 @@ namespace CaritasverbandDuerenJuelichEV.Export
else
{
query.FileName = String.Format("005F{0:yyyyMM}.er2", dt);
var dtMonatlich = ExecuteQuery(GetMonatlicheAbrechnungSql(), dt);
var dtSpitz = ExecuteQuery(GetSpitzabrechnungSql(), dt);
var dtAbgrenzungen = ExecuteQuery(GetAbgrenzungsLvrLwlSql(), dt);
Dictionary<string, string> oid2InvoiceNumbers;
query.QueryResult = GetAbrechnungenString(dt, customerOid, dtAbgrenzungen, out oid2InvoiceNumbers);
query.Attachments = CreateAttachmentFile(dt, dtAbgrenzungen, oid2InvoiceNumbers);
query.QueryResult = GetAbrechnungenString(dt, customerOid, dtMonatlich, dtSpitz, dtAbgrenzungen, out oid2InvoiceNumbers);
query.Attachments = CreateAttachmentFile(dt, dtMonatlich, dtSpitz, dtAbgrenzungen, oid2InvoiceNumbers);
}
}
@@ -158,22 +160,22 @@ namespace CaritasverbandDuerenJuelichEV.Export
public static String GetAbrechnungenString(DateTime date, long? customerOid, DataTable dtAbgrenzungen = null)
{
Dictionary<string, string> _;
return GetAbrechnungenString(date, customerOid, dtAbgrenzungen, out _);
return GetAbrechnungenString(date, customerOid, null, null, dtAbgrenzungen, out _);
}
public static String GetAbrechnungenString(DateTime date, long? customerOid, DataTable dtAbgrenzungen, out Dictionary<string, string> oid2InvoiceNumbers)
public static String GetAbrechnungenString(DateTime date, long? customerOid, DataTable dtMonatlich, DataTable dtSpitz, DataTable dtAbgrenzungen, out Dictionary<string, string> oid2InvoiceNumbers)
{
StringBuilder sb = new StringBuilder();
// 1. Monatliche Abrechnungen
var s = GetMonatlicheAbrechnungString(date, customerOid);
var s = GetMonatlicheAbrechnungString(date, customerOid, dtMonatlich);
if (!String.IsNullOrWhiteSpace(s))
{
sb.Append(s);
}
// 2. Spitzabrechnungen
s = GetSpitzabrechnungString(date, customerOid);
s = GetSpitzabrechnungString(date, customerOid, dtSpitz);
if (!String.IsNullOrWhiteSpace(s))
{
if (sb.Length > 0)
@@ -182,7 +184,7 @@ namespace CaritasverbandDuerenJuelichEV.Export
}
// 3. Abgrenzungsbuchungen LVR/LWL
// DataTable wird von außen übergeben (aus CreateQuery), um doppelte SQL-Ausführung zu vermeiden.
// DataTables werden von außen übergeben (aus CreateQuery), um doppelte SQL-Ausführung zu vermeiden.
// Falls nicht übergeben (z.B. aus CreateExportString), wird die SQL hier ausgeführt.
var abgrenzungenTable = dtAbgrenzungen ?? ExecuteQuery(GetAbgrenzungsLvrLwlSql(), date);
s = GetAbgrenzungsString(abgrenzungenTable, out oid2InvoiceNumbers);
@@ -199,19 +201,19 @@ namespace CaritasverbandDuerenJuelichEV.Export
return sb.ToString();
}
public static String GetMonatlicheAbrechnungString(DateTime date, long? customerOid)
public static String GetMonatlicheAbrechnungString(DateTime date, long? customerOid, DataTable dtMonatlich = null)
{
// Export enthält Rechnungsangaben Zeilen (Zeile F) und Kostenstellen/Rechnungspositionsangaben (Zeile K) in zwei Zeilen
// Kommen aus Export in einer Zeile und werden hier getrennt, aber nur falls die Rechnung mehrere Positionen hat
// Systemrechnungsnummern (ib.InvoiceNumber) werden direkt verwendet, kein Generator
var dt = ExecuteQuery(GetMonatlicheAbrechnungSql(), date);
var dt = dtMonatlich ?? ExecuteQuery(GetMonatlicheAbrechnungSql(), date);
return BuildDiamantLines(dt, null);
}
public static String GetSpitzabrechnungString(DateTime date, long? customerOid)
public static String GetSpitzabrechnungString(DateTime date, long? customerOid, DataTable dtSpitz = null)
{
// Systemrechnungsnummern (ib.InvoiceNumber) werden direkt verwendet, kein Generator
var dt = ExecuteQuery(GetSpitzabrechnungSql(), date);
var dt = dtSpitz ?? ExecuteQuery(GetSpitzabrechnungSql(), date);
return BuildDiamantLines(dt, null);
}
@@ -559,49 +561,36 @@ ORDER BY stunden.LastName, stunden.FirstName
return sql;
}
private static List<FileAttachmentDC> CreateAttachmentFile(DateTime date, DataTable dtAbgrenzungen, Dictionary<string, string> oid2GeneratedNumber)
private static List<FileAttachmentDC> CreateAttachmentFile(DateTime date, DataTable dtMonatlich, DataTable dtSpitz, DataTable dtAbgrenzungen, Dictionary<string, string> oid2GeneratedNumber)
{
try
{
// Spalten aus der bereits ausgeführten Abgrenzungs-DataTable verwenden:
// 0 = OID, 11 = DebitorNumber, 12 = 'Abgrenzung OrgName', 15 = Betrag, 16 = 'Abgr. Nachname, Vorname'
DataTable table = new DataTable();
string[] spalten = { "Rechnungsnr.", "Empfänger", "Debitornr.", "Erlöskonto", "Kostenstelle", "Verwendung", "Betrag" };
foreach (var spalte in spalten)
table.Columns.Add(spalte, typeof(string));
// Block 1: Rechnungen (monatliche Abrechnungen + Spitzabrechnungen) mit Zwischensumme
decimal summeRechnungen = 0;
DataTable tableRechnungen = CreateBelegTable();
summeRechnungen += AddBelegRows(tableRechnungen, dtMonatlich, null, null, "Re. ");
summeRechnungen += AddBelegRows(tableRechnungen, dtSpitz, null, null, "Re. ");
AddSummenRow(tableRechnungen, "Summe Rechnungen", summeRechnungen);
foreach (DataRow booking in dtAbgrenzungen.Rows)
{
string oid = booking[0].ToString();
string invoiceNumber = String.Empty;
if (oid2GeneratedNumber != null && oid2GeneratedNumber.ContainsKey(oid))
invoiceNumber = oid2GeneratedNumber[oid];
// Block 2 (nach Seitenumbruch): Abgrenzungsbuchungen mit Zwischensumme und Gesamtsumme
decimal summeAbgrenzungen = 0;
DataTable tableAbgrenzungen = CreateBelegTable();
summeAbgrenzungen += AddBelegRows(tableAbgrenzungen, dtAbgrenzungen, oid2GeneratedNumber, "Abgrenzung ", "Abgr. ");
AddSummenRow(tableAbgrenzungen, "Summe Abgrenzungen", summeAbgrenzungen);
AddSummenRow(tableAbgrenzungen, "Gesamtsumme", summeRechnungen + summeAbgrenzungen);
string erloeskonto = SetKonto(booking[12]);
var reportRechnungen = CreateBelegReport(String.Format("Buchungsbeleg {0:MMMM yyyy} - Rechnungen", date), tableRechnungen);
var reportAbgrenzungen = CreateBelegReport(String.Format("Buchungsbeleg {0:MMMM yyyy} - Abgrenzungsbuchungen", date), tableAbgrenzungen);
DataRow row = table.NewRow();
row[0] = invoiceNumber;
row[1] = booking[12].ToString().Replace("Abgrenzung ", "");
row[2] = booking[11];
row[3] = erloeskonto;
row[4] = booking[36]; // c.CostCenter
row[5] = booking[16].ToString().Replace("Abgr. ", "");
row[6] = String.Format("{0:0.00}", booking[15]);
table.Rows.Add(row);
}
var queryReportObject = QueryRO.Create(new Query() { Title = "Export" }, table);
queryReportObject.Name = String.Format("Abgrenzungsbuchungen {0:MMMM yyyy}", date);
var queryReport = new Bericht();
queryReport.SetReportDataSource(queryReportObject);
queryReport.CreateDocument();
// Beide Berichte zu einem PDF zusammenführen → Abgrenzungen beginnen auf neuer Seite
reportRechnungen.Pages.AddRange(reportAbgrenzungen.Pages);
reportRechnungen.PrintingSystem.ContinuousPageNumbering = true;
var pdf = new FileAttachmentDC();
pdf.FileName = String.Format("Abgrenzungsbuchungen{0:MMyyyy}.pdf", date);
pdf.FileName = String.Format("Buchungsbeleg{0:MMyyyy}.pdf", date);
using (var ms = new MemoryStream())
{
queryReport.ExportToPdf(ms);
reportRechnungen.ExportToPdf(ms);
pdf.BinaryData = ms.ToArray();
}
@@ -613,6 +602,87 @@ ORDER BY stunden.LastName, stunden.FirstName
}
}
private static DataTable CreateBelegTable()
{
DataTable table = new DataTable();
string[] spalten = { "Rechnungsnr.", "Empfänger", "Debitornr.", "Erlöskonto", "Kostenstelle", "Verwendung", "Betrag" };
foreach (var spalte in spalten)
{
table.Columns.Add(spalte, typeof(string));
}
return table;
}
// Spaltenpositionen sind in allen drei Buchungs-DataTables identisch:
// 0 = OID, 10 = InvoiceNumber, 11 = DebitorNumber, 12 = Buchungstext, 15 = Betrag, 16 = Verwendung, 36 = c.CostCenter
// Dedupliziert wie BuildDiamantLines über die OID (Spalte 0), damit Rechnungen mit mehreren Positionen nur einmal (F-Zeilen-Betrag) erscheinen.
// Rückgabe: Summe der Beträge der ausgegebenen Zeilen.
private static decimal AddBelegRows(DataTable table, DataTable dtBookings, Dictionary<string, string> oid2GeneratedNumber, string empfaengerPrefix, string verwendungPrefix)
{
decimal summe = 0;
HashSet<string> seenOids = new HashSet<string>();
foreach (DataRow booking in dtBookings.Rows)
{
string oid = booking[0].ToString();
if (!seenOids.Add(oid))
{
continue;
}
string invoiceNumber = booking[10].ToString();
if (oid2GeneratedNumber != null && oid2GeneratedNumber.ContainsKey(oid))
{
invoiceNumber = oid2GeneratedNumber[oid];
}
string empfaenger = booking[12].ToString();
if (!String.IsNullOrEmpty(empfaengerPrefix))
{
empfaenger = empfaenger.Replace(empfaengerPrefix, "");
}
string verwendung = booking[16].ToString();
if (!String.IsNullOrEmpty(verwendungPrefix))
{
verwendung = verwendung.Replace(verwendungPrefix, "");
}
DataRow row = table.NewRow();
row[0] = invoiceNumber;
row[1] = empfaenger;
row[2] = booking[11];
row[3] = SetKonto(booking[12]);
row[4] = booking[36];
row[5] = verwendung;
row[6] = String.Format("{0:0.00}", booking[15]);
table.Rows.Add(row);
summe += Convert.ToDecimal(booking[15]);
}
return summe;
}
private static void AddSummenRow(DataTable table, string label, decimal summe)
{
DataRow row = table.NewRow();
row[5] = label;
row[6] = String.Format("{0:0.00}", summe);
table.Rows.Add(row);
}
private static Bericht CreateBelegReport(string name, DataTable table)
{
var queryReportObject = QueryRO.Create(new Query() { Title = "Export" }, table);
queryReportObject.Name = name;
var queryReport = new Bericht();
queryReport.SetReportDataSource(queryReportObject);
queryReport.CreateDocument();
return queryReport;
}
public static DataTable ExecuteQuery(String sql, DateTime dt)
{
var newsql = sql;

View File

@@ -58,6 +58,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Calculations\CustomServiceRecordStatisticFactory.cs" />
<Compile Include="CustomReportCreator.cs" />
<Compile Include="EmployeeKilometerauswertungsListReport.cs">
<SubType>Component</SubType>
</Compile>

View File

@@ -0,0 +1,81 @@
using System.Collections.Generic;
using BeWo.Data.Access;
using BeWo.Data.Entities;
using BeWo.Report;
using BS.Shared;
using DevExpress.XtraReports.UI;
namespace CaritasverbandDuerenJuelichEV
{
public class CustomReportCreator : DefaultReportCreator
{
/// Sammeldruck aus der Rechnungsuebersicht ("Ausgewaehlte drucken"):
/// An jede Rechnung wird automatisch der Quittierungsbeleg angehaengt - wie beim Einzeldruck "mit Quittierungsbeleg".
public override XtraReport CreateInvoiceListReport(List<long> oids)
{
XtraReport master = null;
var ibList = DAOFactory.GenericDAO.LoadByIDs<InvoiceBase>(oids);
foreach (var ib in ibList)
{
XtraReport report = null;
if (ib.Type == InvoiceType.Service)
{
report = CreateServiceInvoiceReport(null, ib.Oid);
}
else if (ib.Type == InvoiceType.Settlement)
{
report = CreateSettlementReport(null, ib.Oid);
}
else
{
report = CreateCustomerInvoiceReport(ib.Oid.Value);
}
if (report != null)
{
report.Watermark.PageRange = "1";
if (report.Pages.Count == 0)
{
report.CreateDocument();
}
var qb = CreateBelegeForInvoice(ib);
AddReportPagesToMaster(report, qb);
if (master == null)
{
master = report;
}
else
{
XRWatermark wm = new XRWatermark();
wm.CopyFrom(report.Watermark);
bool firstpage = true;
foreach (var item in report.Pages)
{
var page2add = item as DevExpress.XtraPrinting.Page;
if (page2add != null)
{
master.Pages.Add(page2add);
if (firstpage)
{
var newpage = master.Pages[master.Pages.Count - 1];
newpage.AssignWatermark(wm);
}
}
firstpage = false;
}
}
}
}
if (master == null)
{
master = new XtraReport();
}
master.PrintingSystem.Document.Name = "Sammeldruck";
return master;
}
}
}

View File

@@ -33,7 +33,7 @@ namespace CaritasverbandDuerenJuelichEV
DevExpress.XtraReports.UI.XRWatermark xrWatermark1 = new DevExpress.XtraReports.UI.XRWatermark();
this.Detail = new DevExpress.XtraReports.UI.DetailBand();
this.ReportHeader = new DevExpress.XtraReports.UI.ReportHeaderBand();
this.xrLabel2 = new DevExpress.XtraReports.UI.XRLabel();
this.lblRechnungsnamen = new DevExpress.XtraReports.UI.XRLabel();
this.ruleRateFactorNull = new DevExpress.XtraReports.UI.FormattingRule();
this.topMarginBand1 = new DevExpress.XtraReports.UI.TopMarginBand();
this.bottomMarginBand1 = new DevExpress.XtraReports.UI.BottomMarginBand();
@@ -113,10 +113,10 @@ namespace CaritasverbandDuerenJuelichEV
this.GroupFooter1 = new DevExpress.XtraReports.UI.GroupFooterBand();
this.bindingSource1 = new System.Windows.Forms.BindingSource(this.components);
this.ReportFooter = new DevExpress.XtraReports.UI.ReportFooterBand();
this.xrPictureBox1 = new DevExpress.XtraReports.UI.XRPictureBox();
this.xrLabel15 = new DevExpress.XtraReports.UI.XRLabel();
this.xrLabel1 = new DevExpress.XtraReports.UI.XRLabel();
this.xrLabel5 = new DevExpress.XtraReports.UI.XRLabel();
this.xrPictureBox1 = new DevExpress.XtraReports.UI.XRPictureBox();
((System.ComponentModel.ISupportInitialize)(this.xrTable5)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.xrTable2)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.xrTable6)).BeginInit();
@@ -135,25 +135,28 @@ namespace CaritasverbandDuerenJuelichEV
// ReportHeader
//
this.ReportHeader.Controls.AddRange(new DevExpress.XtraReports.UI.XRControl[] {
this.xrLabel2});
this.lblRechnungsnamen});
this.ReportHeader.Dpi = 254F;
this.ReportHeader.Font = new DevExpress.Drawing.DXFont("Verdana", 10F);
this.ReportHeader.HeightF = 381.5291F;
this.ReportHeader.Name = "ReportHeader";
this.ReportHeader.StylePriority.UseFont = false;
//
// xrLabel2
// lblRechnungsnamen
//
this.xrLabel2.Borders = DevExpress.XtraPrinting.BorderSide.None;
this.xrLabel2.Dpi = 254F;
this.xrLabel2.Font = new DevExpress.Drawing.DXFont("Arial", 9.75F, DevExpress.Drawing.DXFontStyle.Regular, DevExpress.Drawing.DXGraphicsUnit.Point, new DevExpress.Drawing.DXFontAdditionalProperty[] {
this.lblRechnungsnamen.Borders = DevExpress.XtraPrinting.BorderSide.None;
this.lblRechnungsnamen.CanGrow = false;
this.lblRechnungsnamen.Dpi = 254F;
this.lblRechnungsnamen.Font = new DevExpress.Drawing.DXFont("Arial", 9.75F, DevExpress.Drawing.DXFontStyle.Regular, DevExpress.Drawing.DXGraphicsUnit.Point, new DevExpress.Drawing.DXFontAdditionalProperty[] {
new DevExpress.Drawing.DXFontAdditionalProperty("GdiCharSet", ((byte)(0)))});
this.xrLabel2.LocationFloat = new DevExpress.Utils.PointFloat(733.4296F, 193.9921F);
this.xrLabel2.Name = "xrLabel2";
this.xrLabel2.Padding = new DevExpress.XtraPrinting.PaddingInfo(5, 5, 0, 0, 254F);
this.xrLabel2.SizeF = new System.Drawing.SizeF(153.4583F, 58.42004F);
this.xrLabel2.StylePriority.UseBorders = false;
this.xrLabel2.StylePriority.UseFont = false;
this.lblRechnungsnamen.ForeColor = System.Drawing.Color.Transparent;
this.lblRechnungsnamen.LocationFloat = new DevExpress.Utils.PointFloat(847.2004F, 193.9921F);
this.lblRechnungsnamen.Name = "lblRechnungsnamen";
this.lblRechnungsnamen.Padding = new DevExpress.XtraPrinting.PaddingInfo(5, 5, 0, 0, 254F);
this.lblRechnungsnamen.SizeF = new System.Drawing.SizeF(39.6875F, 58.42004F);
this.lblRechnungsnamen.StylePriority.UseBorders = false;
this.lblRechnungsnamen.StylePriority.UseFont = false;
this.lblRechnungsnamen.StylePriority.UseForeColor = false;
//
// ruleRateFactorNull
//
@@ -1453,6 +1456,15 @@ namespace CaritasverbandDuerenJuelichEV
this.ReportFooter.HeightF = 506.1849F;
this.ReportFooter.Name = "ReportFooter";
//
// xrPictureBox1
//
this.xrPictureBox1.Dpi = 254F;
this.xrPictureBox1.ImageSource = new DevExpress.XtraPrinting.Drawing.ImageSource("img", resources.GetString("xrPictureBox1.ImageSource"));
this.xrPictureBox1.LocationFloat = new DevExpress.Utils.PointFloat(65.36116F, 350.0807F);
this.xrPictureBox1.Name = "xrPictureBox1";
this.xrPictureBox1.SizeF = new System.Drawing.SizeF(441.7936F, 156.1042F);
this.xrPictureBox1.Sizing = DevExpress.XtraPrinting.ImageSizeMode.ZoomImage;
//
// xrLabel15
//
this.xrLabel15.Dpi = 254F;
@@ -1492,15 +1504,6 @@ namespace CaritasverbandDuerenJuelichEV
this.xrLabel5.StylePriority.UseFont = false;
this.xrLabel5.Text = "Mit freundlichen Grüßen";
//
// xrPictureBox1
//
this.xrPictureBox1.Dpi = 254F;
this.xrPictureBox1.ImageSource = new DevExpress.XtraPrinting.Drawing.ImageSource("img", resources.GetString("xrPictureBox1.ImageSource"));
this.xrPictureBox1.LocationFloat = new DevExpress.Utils.PointFloat(65.36116F, 350.0807F);
this.xrPictureBox1.Name = "xrPictureBox1";
this.xrPictureBox1.SizeF = new System.Drawing.SizeF(441.7936F, 156.1042F);
this.xrPictureBox1.Sizing = DevExpress.XtraPrinting.ImageSizeMode.ZoomImage;
//
// ServiceInvoiceReport
//
this.Bands.AddRange(new DevExpress.XtraReports.UI.Band[] {
@@ -1526,6 +1529,7 @@ namespace CaritasverbandDuerenJuelichEV
this.Version = "23.2";
xrWatermark1.Id = "Watermark1";
this.Watermarks.Add(xrWatermark1);
this.AfterPrint += new System.EventHandler(this.ChangeName);
((System.ComponentModel.ISupportInitialize)(this.xrTable5)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.xrTable2)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.xrTable6)).EndInit();
@@ -1564,7 +1568,7 @@ namespace CaritasverbandDuerenJuelichEV
private DevExpress.XtraReports.UI.XRTableCell xrTableCell7;
private DevExpress.XtraReports.UI.XRLabel xrLabel9;
private DevExpress.XtraReports.UI.XRLabel xrLabel13;
private DevExpress.XtraReports.UI.XRLabel xrLabel2;
private DevExpress.XtraReports.UI.XRLabel lblRechnungsnamen;
private DevExpress.XtraReports.UI.XRTable xrTable2;
private DevExpress.XtraReports.UI.XRTableRow xrTableRow2;
private DevExpress.XtraReports.UI.XRTableCell xrTableCell1;

View File

@@ -20,6 +20,7 @@ namespace CaritasverbandDuerenJuelichEV
public void SetReportDataSource(ServiceInvoiceRO pRO)
{
lblRechnungsnummer.Text = pRO.InvoiceNumber;
lblRechnungsnamen.Text = pRO.CustomerLastName + ", " + pRO.CustomerFirstName + " - RE" + pRO.InvoiceNumber;
lblBewZeitraum.Text = String.Format("{0:dd.MM.yyyy} bis {1:dd.MM.yyyy}", pRO.InvoiceBase.SupportConceptCostBearerRelDc.StartDate, pRO.InvoiceBase.SupportConceptCostBearerRelDc.EndDate);
SetBetreuung(pRO);
@@ -95,5 +96,10 @@ namespace CaritasverbandDuerenJuelichEV
}
}
}
private void ChangeName(object sender, EventArgs e)
{
PrintingSystem.Document.Name = lblRechnungsnamen.Text;
}
}
}

File diff suppressed because one or more lines are too long

View File

@@ -89,7 +89,6 @@
<DependentUpon>ServiceInvoiceReport.cs</DependentUpon>
</Compile>
<Compile Include="Statistics\CustomServiceRecordStatisticFactory.cs" />
<Compile Include="Validation\ServiceRecordValidator.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Data\Data.csproj">

View File

@@ -1,64 +0,0 @@
using System;
using System.Collections.Generic;
using BeWo.Data.Access;
using BeWo.Data.Entities;
using BeWo.Service.Plugins;
using BS.Shared;
using BS.Shared.DataContracts;
namespace LebenshilfeBadKreuznach.Validation
{
public class CustomServiceRecordValidator : ServiceRecordValidator
{
public override List<ServiceRecordValidationResultDC> ValidateServiceRecord(ServiceRecordDC newServiceRecord, SupportConceptStatisticsDC statistics,
int maxDaysEditServiceRecordsAllowed, IList<long> employeeOids, IList<long> cb2scOids)
{
var list = base.ValidateServiceRecord(newServiceRecord, statistics, maxDaysEditServiceRecordsAllowed, employeeOids, cb2scOids);
var newResult = new List<ServiceRecordValidationResultDC>();
foreach (var item in list)
{
if (item.ResultType != ServiceRecordValidationResult.ApprovedFLSOverspending && (String.IsNullOrEmpty(item.Message) || !item.Message.Contains("liegt außerhalb des Hilfeplanzeitraums")))
{
newResult.Add(item);
}
}
if (statistics != null && statistics.PeriodStatistics != null)
{
foreach (var stat in statistics.PeriodStatistics)
{
if (stat.SupportConceptApprovalPeriod != null && stat.SupportConceptApprovalPeriod.ServiceCategory != null)
{
if (stat.SupportConceptApprovalPeriod.ServiceCategory.ServiceCategoryOid == newServiceRecord.ServiceDescription.Category.ServiceCategoryOid)
{
decimal newMinutes = newServiceRecord.RoundedDuration;
if (newMinutes + stat.MinutesProvidedThisMonth > stat.MinutesApprovedPerMonth)
{
var klient = "diesen Hilfeplan";
if (newServiceRecord.Customer != null)
{
klient = BS.Shared.Translation.Translator.Translate("Klient/in") + " " + newServiceRecord.Customer.LastNameFirstName;
}
var msg = string.Format("Die für {2} genehmigten FLS ({0:N}) werden mit diesem Eintrag ({1:N}) überschritten.", stat.MinutesApprovedPerMonth / 60, newMinutes / 60, klient);
var dc = new ServiceRecordValidationResultDC
{
ResultType = ServiceRecordValidationResult.Custom,
Message = msg,
Allow = false
};
newResult.Add(dc);
}
}
}
}
}
return newResult;
}
}
}

View File

@@ -110,69 +110,72 @@ namespace SBBMainzReports.Invoicing
{
var calc = PluginLoader.FindClass<Calculations>(_SpecificID) ?? Calculations.GetInstance(_SpecificID);
var scap = supportConceptApprovalPeriod;
if (scap.ServiceCategory != null)
{
var crList = scap.ServiceCategory.CostRatePeriods;
var cr = crList.GetCostRatePeriodForDate(BS.Shared.CostRatePeriodType.AmountOfMoney, serviceInvoicePeriod.Start.Value);
if (cr != null && cr.CostRateValue.HasValue)
{
decimal? hourlyRate = cr.CostRateValue.Value;
decimal weeklyFactor = 4.33m;
// Anteilige Berechnung nur in dem Monat, in dem der HP tatsächlich beginnt bzw. endet -
// in allen anderen (vollen) Monaten wird der volle Monatsfaktor berechnet
if (scap.StartDate.HasValue && scap.StartDate.Value.Day > 7 && serviceInvoicePeriod.Start.HasValue
&& scap.StartDate.Value.Year == serviceInvoicePeriod.Start.Value.Year && scap.StartDate.Value.Month == serviceInvoicePeriod.Start.Value.Month)
if (cr != null && cr.CostRateValue.HasValue)
{
int startDay = scap.StartDate.Value.Day;
if (startDay <= 14)
decimal? hourlyRate = cr.CostRateValue.Value;
decimal weeklyFactor = 4.33m;
// Anteilige Berechnung nur in dem Monat, in dem der HP tatsächlich beginnt bzw. endet -
// in allen anderen (vollen) Monaten wird der volle Monatsfaktor berechnet
if (scap.StartDate.HasValue && scap.StartDate.Value.Day > 7 && serviceInvoicePeriod.Start.HasValue
&& scap.StartDate.Value.Year == serviceInvoicePeriod.Start.Value.Year && scap.StartDate.Value.Month == serviceInvoicePeriod.Start.Value.Month)
{
weeklyFactor = Math.Min(weeklyFactor, 3m);
int startDay = scap.StartDate.Value.Day;
if (startDay <= 14)
{
weeklyFactor = Math.Min(weeklyFactor, 3m);
}
else if (startDay <= 21)
{
weeklyFactor = Math.Min(weeklyFactor, 2m);
}
else
{
weeklyFactor = Math.Min(weeklyFactor, 1m);
}
}
else if (startDay <= 21)
if (scap.EndDate.HasValue && scap.EndDate.Value.Day < 22 && serviceInvoicePeriod.End.HasValue
&& scap.EndDate.Value.Year == serviceInvoicePeriod.End.Value.Year && scap.EndDate.Value.Month == serviceInvoicePeriod.End.Value.Month)
{
weeklyFactor = Math.Min(weeklyFactor, 2m);
int endDay = scap.EndDate.Value.Day;
if (endDay >= 15)
{
weeklyFactor = Math.Min(weeklyFactor, 3m);
}
else if (endDay >= 8)
{
weeklyFactor = Math.Min(weeklyFactor, 2m);
}
else
{
weeklyFactor = Math.Min(weeklyFactor, 1m);
}
}
else
{
weeklyFactor = Math.Min(weeklyFactor, 1m);
}
}
if (scap.EndDate.HasValue && scap.EndDate.Value.Day < 22 && serviceInvoicePeriod.End.HasValue
&& scap.EndDate.Value.Year == serviceInvoicePeriod.End.Value.Year && scap.EndDate.Value.Month == serviceInvoicePeriod.End.Value.Month)
{
int endDay = scap.EndDate.Value.Day;
if (endDay >= 15)
{
weeklyFactor = Math.Min(weeklyFactor, 3m);
}
else if (endDay >= 8)
{
weeklyFactor = Math.Min(weeklyFactor, 2m);
}
else
{
weeklyFactor = Math.Min(weeklyFactor, 1m);
}
}
decimal approvedHours = 0;
decimal approvedHoursMonth = 0;
if (scap.ApprovedBEInterval.HasValue && scap.ApprovedBEInterval.Value == SupportConceptApprovalInterval.Weekly && scap.ApprovedBEPerInterval.HasValue)
{
approvedHours = scap.ApprovedBEPerInterval.Value;
approvedHoursMonth = weeklyFactor * scap.ApprovedBEPerInterval.Value;
decimal approvedHours = 0;
decimal approvedHoursMonth = 0;
if (scap.ApprovedBEInterval.HasValue && scap.ApprovedBEInterval.Value == SupportConceptApprovalInterval.Weekly && scap.ApprovedBEPerInterval.HasValue)
{
approvedHours = scap.ApprovedBEPerInterval.Value;
approvedHoursMonth = weeklyFactor * scap.ApprovedBEPerInterval.Value;
}
decimal amount = approvedHoursMonth * hourlyRate.Value;
serviceInvoicePeriod.InvoiceItemList.Add(new InvoiceItem
{
AmountTotal = amount,
GrossAmountTotal = amount,
ItemPeriodStart = serviceInvoicePeriod.Start,
ItemPeriodEnd = serviceInvoicePeriod.End,
AmountPerUnit = hourlyRate.Value,
ItemDescription = "Fachleistungseinheiten/Woche",
UnitDescription = "QA/Woche",
UnitCount = approvedHours,
Notice = approvedHoursMonth.ToString("n2")
});
}
decimal amount = approvedHoursMonth * hourlyRate.Value;
serviceInvoicePeriod.InvoiceItemList.Add(new InvoiceItem
{
AmountTotal = amount,
GrossAmountTotal = amount,
ItemPeriodStart = serviceInvoicePeriod.Start,
ItemPeriodEnd = serviceInvoicePeriod.End,
AmountPerUnit = hourlyRate.Value,
ItemDescription = "Fachleistungseinheiten/Woche",
UnitDescription = "QA/Woche",
UnitCount = approvedHours,
Notice = approvedHoursMonth.ToString("n2")
});
}
}

View File

@@ -5,7 +5,9 @@ using BeWo.Report.ReportObjects;
using BS.Shared.Extensions;
using DevExpress.XtraReports.UI;
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
namespace SBBMainzReports
@@ -31,6 +33,8 @@ namespace SBBMainzReports
{
lblReName.Text = lblReName.Text.Replace("/", "-");
}
//SanitizeFilename auch in BS.Shard.Core aufgenommen, brauchte es aber hier sofort
lblReName.Text = SanitizeFilename(lblReName.Text);
if (start.Month == end.Month && start.Year == end.Year)
{
lblAbrechnungszeitraum.Text = String.Format("{0:MMMM yyyy}", start);
@@ -143,5 +147,30 @@ namespace SBBMainzReports
{
PrintingSystem.Document.Name = String.Format("{0}", lblReName.Text);
}
private static readonly char[] InvalidFilenameChars = Path.GetInvalidFileNameChars();
public static bool ContainsInvalidFilenameChars(string fileName)
{
return fileName.IndexOfAny(InvalidFilenameChars) >= 0;
}
public static string SanitizeFilename(string fileName)
{
if (String.IsNullOrEmpty(fileName) || !ContainsInvalidFilenameChars(fileName))
{
return fileName;
}
var sb = new StringBuilder(fileName.Length);
foreach (char c in fileName)
{
if (!InvalidFilenameChars.Contains(c))
{
sb.Append(c);
}
}
return sb.ToString();
}
}
}

View File

@@ -228,7 +228,7 @@ SELECT
INNER JOIN `servicecategory` sc ON sd.`ServiceCategoryOid` = sc.`Oid`
WHERE sr2.`StartDate` >= ':Monat_Start' AND sr2.`StartDate` < ':Monat_End' AND sc.`Billable` = 1 and sd.Name <> 'Fehlkontakt' GROUP BY sr2.`CostBearer2SupportConceptOid`)
AS sr ON sr.`CostBearer2SupportConceptOid` = cb2sc.`Oid`
WHERE c.`IsActive` = 1 AND sc.`IsActive` = 1 and (org.Name = 'LVR' OR org.Name = 'LWL')
WHERE c.`IsActive` = 1 AND sc.`IsActive` <> 0 and (org.Name = 'LVR' OR org.Name = 'LWL')
and (sr.`GeleisteteFLM` is not null)
UNION
(SELECT
@@ -251,7 +251,7 @@ SELECT
INNER JOIN `servicecategory` sc ON sd.`ServiceCategoryOid` = sc.`Oid`
WHERE sr2.`StartDate` >= ':Monat_Start' AND sr2.`StartDate` < ':Monat_End' AND sc.`Billable` = 1 and sd.Name = 'Fehlkontakt' GROUP BY sr2.`CostBearer2SupportConceptOid`)
AS sr ON sr.`CostBearer2SupportConceptOid` = cb2sc.`Oid`
WHERE c.`IsActive` = 1 AND sc.`IsActive` = 1 and (org.Name = 'LVR' OR org.Name = 'LWL')
WHERE c.`IsActive` = 1 AND sc.`IsActive` <> 0 and (org.Name = 'LVR' OR org.Name = 'LWL')
and (sr.`GeleisteteFLM` is not null)))
)qry
GROUP BY qry.OID

View File

@@ -17,6 +17,24 @@ namespace BS.Shared.Core
return fileName.IndexOfAny(InvalidFilenameChars) >= 0;
}
public static string SanitizeFilename(string fileName)
{
if (String.IsNullOrEmpty(fileName) || !ContainsInvalidFilenameChars(fileName))
{
return fileName;
}
var sb = new StringBuilder(fileName.Length);
foreach (char c in fileName)
{
if (!InvalidFilenameChars.Contains(c))
{
sb.Append(c);
}
}
return sb.ToString();
}
public static string GetChecksum(string filePath)
{
using (FileStream stream = File.OpenRead(filePath))