Files
BeWoPlaner/BeWoPlanerMobil/Util/MobileUtils.cs
2026-06-29 13:45:41 +02:00

656 lines
23 KiB
C#

using BeWo.Report.DefaultReports;
using BeWoPlanerMobil.Models;
using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;
using BS.Shared.Extensions;
using BS.Shared.Services;
using Newtonsoft.Json;
using RestSharp;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using BeWo.Service.Plugins;
using BeWoPlanerMobil.Service;
using static System.Int32;
using static System.String;
namespace BeWoPlanerMobil.Util
{
public class MobileUtils
{
public static string TempDataLoginStateKey => "loginstate";
public static string TempDataServiceRecordValidationKey => "ServiceRecordValidationResults";
public static string TempDataFormIdKey => "form-id";
public static List<int> Years
{
get
{
var heuer = DateTime.Today.Year;
var result = new List<int>();
for(var i = heuer + 1; i >= heuer - 10; i--)
{
result.AddIfNotIn(i);
}
return result;
}
}
public static DateTime ConvertTimeStringToDateTime(string timeString)
{
var dt = DateTime.Now.Date;
if (IsNullOrEmpty(timeString))
{
timeString = "0000";
}
var numberString = Regex.Replace(timeString, "[^0-9]", "");
if (numberString.Length < 3)
{
if (numberString.Length < 2)
{
numberString = "0" + numberString;
}
while (numberString.Length < 4)
{
numberString += "0";
}
}
else
{
while (numberString.Length < 4)
{
numberString = "0" + numberString;
}
}
if (numberString.Length > 4)
{
numberString = numberString.Substring(0, 4);
}
var hours = Convert.ToInt32(numberString.Substring(0, 2));
var minutes = Convert.ToInt32(numberString.Substring(2, 2));
dt = dt.AddHours(hours);
dt = dt.AddMinutes(minutes);
return dt;
}
public static DateTime[] ConvertRecordTimes(string start, string ende, DateTime datum, double dauerInMinuten)
{
var result = new DateTime[2];
var startDate = datum.Date;
var endDate = datum.Date;
var dateTemp = ConvertTimeStringToDateTime(start);
startDate = startDate.AddHours(dateTemp.Hour).AddMinutes(dateTemp.Minute);
dateTemp = ConvertTimeStringToDateTime(ende);
endDate = endDate.AddHours(dateTemp.Hour).AddMinutes(dateTemp.Minute);
if (IsNullOrEmpty(start) && !IsNullOrEmpty(ende))
{
startDate = endDate.AddMinutes(-1 * dauerInMinuten);
}
if (IsNullOrEmpty(ende) && !IsNullOrEmpty(start))
{
endDate = startDate.AddMinutes(dauerInMinuten);
}
if (endDate < startDate)
{
endDate = startDate.AddMinutes(dauerInMinuten);
if(endDate < startDate)
{
endDate = startDate;
}
}
result[0] = startDate;
result[1] = endDate;
return result;
}
public static DateTime[] ConvertRecordTimesWithEndDate(string start, string ende, DateTime datum, DateTime enddatum, double dauer)
{
var result = new DateTime[2];
var startDate = datum;
var endDate = enddatum;
const int hours = 0;
const int minutes = 0;
var dateStartTime = ConvertTimeStringToDateTime(start);
startDate = startDate.AddHours(dateStartTime.Hour).AddMinutes(dateStartTime.Minute);
var dateEndTime = ConvertTimeStringToDateTime(ende);
endDate = endDate.AddHours(dateEndTime.Hour).AddMinutes(dateEndTime.Minute);
endDate = endDate.AddHours(hours);
endDate = endDate.AddMinutes(minutes);
if (IsNullOrEmpty(start) && !IsNullOrEmpty(ende))
{
startDate = endDate.AddMinutes(-1 * dauer);
}
if (IsNullOrEmpty(ende) && !IsNullOrEmpty(start))
{
endDate = startDate.AddMinutes(dauer);
}
if (endDate < startDate)
{
endDate = startDate;
}
result[0] = startDate;
result[1] = endDate;
return result;
}
public static string GetSettingValue(string settings, string key)
{
if (!IsNullOrEmpty(settings))
{
if (settings.IndexOf(";") == -1 && settings.IndexOf("=") == -1)
{
return settings;
}
var keyValuePairs = settings.Split(';');
return (from pair in keyValuePairs select pair.Split('=') into keyValuePair where keyValuePair.Length == 2 where keyValuePair[0] == key select keyValuePair[1]).FirstOrDefault();
}
return null;
}
public static bool IsBillable(long serviceDescriptionOid, List<ServiceDescriptionDC> serviceDescriptions)
{
var description = serviceDescriptions.FirstOrDefault(f => f.ServiceDescriptionOid.Equals(serviceDescriptionOid));
return description != null && description.Category.IsBillable;
}
public static decimal? GetDecimalValue(decimal? decValue, int decimalPlaces)
{
return decValue != null ? Math.Round(decValue.Value, decimalPlaces, MidpointRounding.AwayFromZero) : decValue;
}
public static decimal? GetDecimalValueWithMaxDecimal(decimal? decValue, int maxDecimal)
{
if (decValue != null)
{
var decValueStr = decValue.ToString();
decValueStr = decValueStr.Replace(".", ",");
while (decValueStr.Length > 0 && decValueStr.IndexOf(",") > 0 && (decValueStr.EndsWith("0") || decValueStr.EndsWith(",")))
{
decValueStr = decValueStr.Substring(0, decValueStr.Length - 1);
}
var decCount = 0;
if (decValueStr.IndexOf(",") >= 0)
{
decCount = decValueStr.Length - decValueStr.IndexOf(",") - 1;
}
if (maxDecimal >= 0 && maxDecimal < decCount)
{
decCount = maxDecimal;
}
return GetDecimalValue(decValue, decCount);
}
return null;
}
public static List<ServiceCategoryModel> CreateServiceCategoryModels(IEnumerable<ServiceDescriptionDC> serviceDescriptions)
{
var catOid2ModelDict = new Dictionary<long, ServiceCategoryModel>();
foreach (var sd in serviceDescriptions)
{
if (sd.Category.ActivationType == ActivationTypeId.Active)
{
if (!catOid2ModelDict.ContainsKey(sd.Category.ServiceCategoryOid.Value))
{
catOid2ModelDict[sd.Category.ServiceCategoryOid.Value] = new ServiceCategoryModel
{
Name = sd.Category.Name,
IsDefault = sd.Category.IsDefault,
Percentage = sd.Category.Percentage,
Position = sd.Category.Position,
OhneHilfeplan = sd.Category.OhneHilfeplan,
ServiceCategoryOid = sd.Category.ServiceCategoryOid,
ServiceDescriptions = new List<ServiceDescriptionDC>()
};
}
catOid2ModelDict[sd.Category.ServiceCategoryOid.Value].ServiceDescriptions.Add(sd);
}
}
var list = catOid2ModelDict.Values.ToList();
list.Sort((s1, s2) =>
{
if (s1.IsDefault)
{
return 1;
}
return s1.Position != s2.Position ? s1.Position.CompareTo(s2.Position) : s1.ServiceCategoryOid.Value.CompareTo(s2.ServiceCategoryOid.Value);
});
return list;
}
public static FlatSupportConceptTreeNodeDC CreateFlatSupportConceptItem(CompactSupportConceptDC dc, CompactOrganisationDC orga)
{
var flatNode = new FlatSupportConceptTreeNodeDC();
if (dc != null)
{
var treeNode = new SupportConceptTreeNodeDC {SupportConcept = dc, Customer = dc.Customer};
if (dc.CostBearerList.Count > 0)
{
CompactCostBearerDC cbDC = null;
if (orga != null)
{
foreach (var item in dc.CostBearerList)
{
if (orga.Equals(item.Organisation))
{
cbDC = item;
}
}
}
if (cbDC == null)
cbDC = dc.CostBearerList[0];
var orgDC = new CompactOrganisationDC();
var relDC = new SupportConceptCostBearerRelDC();
orgDC.CostBearerID = cbDC.CostBearerID;
orgDC.CostBearerOid = cbDC.CostBearerOid;
var o = orga ?? cbDC.Organisation;
if (o != null)
{
orgDC.OrganisationOid = o.OrganisationOid;
orgDC.Name = o.Name;
orgDC.ActualHourlyRate = o.ActualHourlyRate;
orgDC.ActualMinuteIntervall = o.ActualMinuteIntervall;
orgDC.ActualRateFactor = o.ActualRateFactor;
orgDC.CostRatePeriods = o.CostRatePeriods;
orgDC.IsCalculatingWithFactor = o.IsCalculatingWithFactor;
}
relDC.ApprovedEndDate = cbDC.ApprovedEndDate;
relDC.ApprovedStartDate = cbDC.ApprovedStartDate;
relDC.CostBearer = orgDC;
relDC.CostBearer2SupportConceptOid = cbDC.CostBearer2SupportConceptOid;
relDC.RequestedEndDate = cbDC.RequestedEndDate;
relDC.RequestedStartDate = cbDC.RequestedStartDate;
relDC.Status = cbDC.SupportConceptStatus;
relDC.SupportConcept = dc;
relDC.AuswahlBezeichnung = cbDC.Bezeichnung;
treeNode.SupportConceptCostBearerRelDC = relDC;
treeNode.CostBearer = orgDC;
}
flatNode.SupportConceptTreeNodeDC = treeNode;
}
return flatNode;
}
public static ServiceRecordDC CloneServiceRecord(ServiceRecordDC pOriginal)
{
var m = pOriginal;
var clone = new ServiceRecordDC
{
CostBearer = m.CostBearer,
CostBearer2SupportConceptOid = m.CostBearer2SupportConceptOid,
Customer = m.Customer,
Employee = m.Employee,
End = m.End,
Goals = m.Goals,
GroupEmployeeCount = m.GroupEmployeeCount,
GroupOid = m.GroupOid,
SignatureOid = m.SignatureOid,
GroupPersonCount = m.GroupPersonCount,
GroupRoundedDuration = m.GroupRoundedDuration,
InsUser = m.InsUser,
InsertedOn = m.InsertedOn,
Notice = m.Notice,
Notice2 = m.Notice2,
Notice3 = m.Notice3,
Notice4 = m.Notice4,
Notice5 = m.Notice5,
RTFNotice1 = m.RTFNotice1,
RTFNotice2 = m.RTFNotice2,
RTFNotice3 = m.RTFNotice3,
RTFNotice4 = m.RTFNotice4,
RTFNotice5 = m.RTFNotice5,
RoundedDuration = m.RoundedDuration,
ServiceDescription = m.ServiceDescription,
Start = m.Start,
SupportConcept = m.SupportConcept,
ServiceRecordType = m.ServiceRecordType,
DistanceInMeter = m.DistanceInMeter,
IP = m.IP,
Relevance = m.Relevance,
IsCreatedInMobileClient = true,
WohnheimbuchungsOid = m.WohnheimbuchungsOid,
DurationInStunden = m.DurationInStunden,
ServiceRecordFormat = m.ServiceRecordFormat,
DistanceInMeterDecimal = m.DistanceInMeterDecimal,
Betrag = m.Betrag
};
return clone;
}
public static string SerializeObject(object obj)
{
return JsonConvert.SerializeObject(obj, Formatting.Indented, new JsonSerializerSettings { ContractResolver = new ShouldSerializeContractResolver(), ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
}
public static BeWoLoginState GetLoginState(string tenant)
{
var result = new BeWoLoginState(-1, null);
#if DEBUG
return result;
#endif
var client = new RestClient("https://support.bewoplaner.de/api");
var request = new RestRequest("getstate.php", Method.GET);
request.AddParameter("k", tenant, ParameterType.QueryString);
request.AddParameter("type", 1, ParameterType.QueryString);
var response = client.Execute(request);
return response.Content != null ? DeserializeLoginState(response.Content) : result;
}
private static BeWoLoginState DeserializeLoginState(string state)
{
var responseState = -1;
if (IsNullOrWhiteSpace(state) || !state.Contains(';'))
{
return new BeWoLoginState(responseState, null);
}
var arr = state.Split(';');
var message = arr[0].Replace("\n", "<br />");
var isSuccessful = TryParse(arr[1], out var convertedResponseState);
responseState = isSuccessful ? convertedResponseState : -1;
return new BeWoLoginState(responseState, message.Replace("\\", "\\\\"));
}
public static List<long> ConvertOidStringToList(string oids, char token = ',')
{
var result = new List<long>();
if(IsNullOrWhiteSpace(oids))
{
return result;
}
var oidArray = oids.Trim(token).Split(token);
oidArray.DoForEach(oidString =>
{
var isSuccessful = long.TryParse(oidString, out var oid);
if(isSuccessful)
{
result.AddIfNotIn(oid);
}
});
return result;
}
public static ConvertedDateTimes ConvertStringDatesToDateTimes(string start, string end)
{
try
{
//var isSuccessfulStartDate = DateTime.TryParseExact(start, "dd.MM.yyyy HH:mm", null, DateTimeStyles.None, out var startDate);
//var isSuccessfulEndDate = DateTime.TryParseExact(end, "dd.MM.yyyy HH:mm", null, DateTimeStyles.None, out var endDate);
var isSuccessfulStartDate = DateTime.TryParse(start, out var startDate);
var isSuccessfulEndDate = DateTime.TryParse(end, out var endDate);
if(isSuccessfulStartDate && isSuccessfulEndDate)
{
return new ConvertedDateTimes(startDate, endDate);
}
throw new ArgumentException("Die Datumsstring dürfen nicht null sein und müssen das Format 'dd.MM.yyyy HH:mm' haben.");
}
catch(Exception exception)
{
throw exception;
}
}
public static string ToHtml(string s, bool nofollow)
{
if(s is null)
{
return Empty;
}
s = HttpUtility.HtmlEncode(s);
var paragraphs = s.Split(new[] { "\r\n\r\n" }, StringSplitOptions.None);
var stringBuilder = new StringBuilder();
foreach(var par in paragraphs)
{
stringBuilder.AppendLine($"<p class='text-wrap'>");
var p = par.Replace(Environment.NewLine, "<br />\r\n");
if(nofollow)
{
p = Regex.Replace(p, @"\[\[(.+)\]\[(.+)\]\]", "<a href=\"$2\" rel=\"nofollow\">$1</a>");
p = Regex.Replace(p, @"\[\[(.+)\]\]", "<a href=\"$1\" rel=\"nofollow\">$1</a>");
}
else
{
p = Regex.Replace(p, @"\[\[(.+)\]\[(.+)\]\]", "<a href=\"$2\">$1</a>");
p = Regex.Replace(p, @"\[\[(.+)\]\]", "<a href=\"$1\">$1</a>");
stringBuilder.AppendLine(p);
}
stringBuilder.AppendLine("</p>");
}
return stringBuilder.ToString();
}
public static decimal CalculateRoundedDuration(ServiceRecordDC serviceRecord)
{
if(serviceRecord.End is null || serviceRecord.Start is null)
{
return 0m;
}
var roundedDuration = (decimal) serviceRecord.End.Value.Subtract(serviceRecord.Start.Value).TotalMinutes;
if(serviceRecord.CostBearer2SupportConceptOid.HasValue && (serviceRecord.ServiceDescription?.Category?.IsBillable ?? false))
{
var calculations = Calculations.GetInstance(serviceRecord.CostBearer.CostBearerID);
roundedDuration = calculations.GetRoundedDuration(serviceRecord.CostBearer, serviceRecord.Start.Value, roundedDuration);
}
return roundedDuration;
}
public static string GetRoundedEndDate(ServiceRecordDC serviceRecord)
{
if(serviceRecord.End is null || serviceRecord.Start is null)
{
return Empty;
}
var duration = (double) CalculateRoundedDuration(serviceRecord);
return $"{(serviceRecord.Start.Value.AddMinutes(duration))}";
}
public static string GetColorAsHex(System.Windows.Media.Color color)
{
return $"{color.R:X2}{color.G:X2}{color.B:X2}";
}
public static string ColorArgbToRgbHex(string color)
{
if(color.StartsWith("#") && color.Length == 9)
{
return $"#{color.Substring(3)}";
}
return null;
}
public static string GetAppointmentRightGradient(bool hasCustomers, List<string> colors, int colorCountLimit = 4)
{
if(colors is null)
{
colors = new List<string>();
}
if(colors.Count == 0 && false == hasCustomers)
{
return string.Empty;
}
if(hasCustomers && colors.Count == 0)
{
return "linear-gradient(#3B7799 100.0%)";
}
if(colors.Count > colorCountLimit)
{
colors = colors.GetRange(0, colorCountLimit);
}
var colorCount = colors.Count;
var startingPoint = hasCustomers ? 50 : 0;
var divisor = hasCustomers ? 50 : 100;
if(colorCount == 1)
{
var color = colors.First();
return hasCustomers ? $"linear-gradient(#3B7799 50.0%, {color} 50.0%)" : $"linear-gradient({color})";
}
var result = hasCustomers ? "#3B7799 50.0%, " : string.Empty;
for(var i = 0; i < colorCount; i++)
{
var currentColor = colors[i];
var colorWidth = (double)divisor / colorCount;
var colorStartingPoint = startingPoint + i * colorWidth;
var colorStart = FormattableString.Invariant($"{colorStartingPoint:F1}");
var colorEnd = FormattableString.Invariant($"{colorStartingPoint + colorWidth:F1}");
result += $"{currentColor} {colorStart}%, {currentColor} {colorEnd}%, ";
}
return $"linear-gradient({result.TrimEnd().TrimEnd(',')})";
}
public static string GetAppointmentRightBackground(DevExpress.XtraScheduler.Appointment appointment)
{
if(appointment.CustomFields["IsTask"] is true)
{
return GetAppointmentRightGradient(false, new List<string> { "#993B3B" }, 1);
}
var hasCustomers = appointment.CustomFields["Customers"] is List<CompactCustomerDC> customerList && customerList.Any();
var customFieldValue = appointment.CustomFields["Resources"];
var resourceList = customFieldValue as List<ResourceDC> ?? new List<ResourceDC>();
var resourcesWithColors = resourceList.Where(resource => false == IsNullOrWhiteSpace(resource.Color)).ToList();
var resourceColors = (resourcesWithColors.Count > 4 ? resourcesWithColors.GetRange(0, 4) : resourcesWithColors).Select(resource => ColorArgbToRgbHex(resource.Color)).ToList();
return GetAppointmentRightGradient(hasCustomers, resourceColors);
}
public static string GetLeftAppointmentBorder(DevExpress.XtraScheduler.Appointment appointment)
{
var showEmployeeColors = appointment.CustomFields["ShowEmployeeColors"] is true;
if(false == showEmployeeColors)
{
return "5px solid #C0FFD0";
}
if(appointment.CustomFields[nameof(SchedulerAppointmentDC.Originator)] is CompactEmployeeDC originator && originator.FilterableBrush?.Color != null)
{
var color = originator.FilterableBrush.Color;
return $"5px solid #{GetColorAsHex(color)}";
}
if(appointment.CustomFields["IsTask"] is true)
{
return "5px solid #993B3B";
}
return "5px solid #C0FFD0";
}
public static string GetCssRightValue(DevExpress.XtraScheduler.Appointment appointment)
{
var serviceRecords = appointment.CustomFields[nameof(SchedulerAppointmentDC.ServiceRecordList)] as List<ServiceRecordDC> ?? new List<ServiceRecordDC>();
return serviceRecords.Any() ? "40px" : "23px";
}
}
}