From da52dfe88842551dca3ed284da35d229f949da41 Mon Sep 17 00:00:00 2001 From: rene Date: Wed, 15 Mar 2023 10:09:46 +0100 Subject: [PATCH] Distance Matrix API, noch auf app5 --- Data/Data.csproj | 4 + Data/Entities/Address.cs | 5 + Data/Entities/AddressRoute.cs | 115 ++++++++++++++++++ Data/Mappings/AddressRoute.hbm.xml | 25 ++++ Host/Web.config | 2 + Model/Changes_2023_03_09_AddressRoute.txt | 18 +++ .../AddressRouteDC_AddressRoute.cs | 64 ++++++++++ Service/DCEntityMapper/MapperFactory.cs | 5 + Service/Service.csproj | 5 +- .../OperationsServiceImp.cs | 19 +++ .../API/GoogleDistanceMatrixAPI.cs | 106 ++++++++++++++++ .../Generell/AddressRouteManager.cs | 95 +++++++++++++++ Shared/BeWoEntityEnums.cs | 3 +- Shared/DataContracts/AddressRouteDC.cs | 55 +++++++++ Shared/Shared.csproj | 1 + 15 files changed, 520 insertions(+), 2 deletions(-) create mode 100644 Data/Entities/AddressRoute.cs create mode 100644 Data/Mappings/AddressRoute.hbm.xml create mode 100644 Model/Changes_2023_03_09_AddressRoute.txt create mode 100644 Service/DCEntityMapper/AddressRouteDC_AddressRoute.cs create mode 100644 Service/ServiceUtils/API/GoogleDistanceMatrixAPI.cs create mode 100644 Service/ServiceUtils/Generell/AddressRouteManager.cs create mode 100644 Shared/DataContracts/AddressRouteDC.cs diff --git a/Data/Data.csproj b/Data/Data.csproj index 414469d07..f3d64fb46 100644 --- a/Data/Data.csproj +++ b/Data/Data.csproj @@ -199,6 +199,7 @@ + @@ -709,6 +710,9 @@ + + Designer + Designer diff --git a/Data/Entities/Address.cs b/Data/Entities/Address.cs index fd156065c..0c679db82 100644 --- a/Data/Entities/Address.cs +++ b/Data/Entities/Address.cs @@ -161,5 +161,10 @@ namespace BeWo.Data.Entities Town = this.Town }; } + + public string ToGoogle() + { + return $"{Street}, {PostalCode}, {Town}, {State}, {Country}"; + } } } \ No newline at end of file diff --git a/Data/Entities/AddressRoute.cs b/Data/Entities/AddressRoute.cs new file mode 100644 index 000000000..c45763447 --- /dev/null +++ b/Data/Entities/AddressRoute.cs @@ -0,0 +1,115 @@ +using BS.Shared; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BeWo.Data.Entities +{ + public class AddressRoute : BeWoEntityBase + { + private long address1_oid; + private long address1_version; + private long address2_oid; + private long address2_version; + + private int distance_in_meter; + private int time_in_seconds; + + public AddressRoute() + { + _Tid = TableID.AddressRoute; + } + + public virtual long Address1_Oid + { + get + { + return address1_oid; + } + set + { + if (AreDifferent(address1_oid, value)) + { + address1_oid = value; + } + } + } + + public virtual long Address1_Version + { + get + { + return address1_version; + } + set + { + if (AreDifferent(address1_version, value)) + { + address1_version = value; + } + } + } + + public virtual long Address2_Oid + { + get + { + return address2_oid; + } + set + { + if (AreDifferent(address2_oid, value)) + { + address2_oid = value; + } + } + } + + public virtual long Address2_Version + { + get + { + return address2_version; + } + set + { + if (AreDifferent(address2_version, value)) + { + address2_version = value; + } + } + } + + public virtual int Distance_in_meter + { + get + { + return distance_in_meter; + } + set + { + if (AreDifferent(distance_in_meter, value)) + { + distance_in_meter = value; + } + } + } + + public virtual int Time_in_seconds + { + get + { + return time_in_seconds; + } + set + { + if (AreDifferent(time_in_seconds, value)) + { + time_in_seconds = value; + } + } + } + } +} diff --git a/Data/Mappings/AddressRoute.hbm.xml b/Data/Mappings/AddressRoute.hbm.xml new file mode 100644 index 000000000..cf0a9649b --- /dev/null +++ b/Data/Mappings/AddressRoute.hbm.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Host/Web.config b/Host/Web.config index 0ec77dd6d..8b98d17ec 100644 --- a/Host/Web.config +++ b/Host/Web.config @@ -219,6 +219,8 @@ + + diff --git a/Model/Changes_2023_03_09_AddressRoute.txt b/Model/Changes_2023_03_09_AddressRoute.txt new file mode 100644 index 000000000..ce4c5aae7 --- /dev/null +++ b/Model/Changes_2023_03_09_AddressRoute.txt @@ -0,0 +1,18 @@ +CREATE TABLE `AddressRoute` ( + `Oid` bigint NOT NULL AUTO_INCREMENT, + `Tid` int DEFAULT NULL, + `IsActive` tinyint DEFAULT NULL, + `Notice` varchar(1024) DEFAULT NULL, + `InsTs` datetime DEFAULT NULL, + `InsUser` varchar(256) DEFAULT NULL, + `Version` bigint DEFAULT NULL, + `UdpUser` varchar(256) DEFAULT NULL, + `SystemEntryID` int DEFAULT NULL, + `Address1Oid` bigint DEFAULT NULL, + `Address1Version` bigint DEFAULT NULL, + `Address2Oid` bigint DEFAULT NULL, + `Address2Version` bigint DEFAULT NULL, + `DistanceMeter` int DEFAULT NULL, + `TimeSec` int DEFAULT NULL, + PRIMARY KEY (`Oid`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; \ No newline at end of file diff --git a/Service/DCEntityMapper/AddressRouteDC_AddressRoute.cs b/Service/DCEntityMapper/AddressRouteDC_AddressRoute.cs new file mode 100644 index 000000000..5e98dfe15 --- /dev/null +++ b/Service/DCEntityMapper/AddressRouteDC_AddressRoute.cs @@ -0,0 +1,64 @@ +using BeWo.Data.Entities; +using BS.Shared.DataContracts; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BeWo.Service.DCEntityMapper +{ + public class AddressRouteDC_AddressRoute : AbstractIDCEntityMapper + { + public override AddressRouteDC MergeWithDC(AddressRoute pEntity, AddressRouteDC pDataContract) + { + pDataContract.Oid = pEntity.Oid; + pDataContract.IsActive = pEntity.IsActive; + pDataContract.Notice = pEntity.Notice; + pDataContract.InsTs = pEntity.InsTs; + pDataContract.InsUser = pEntity.InsUser; + pDataContract.Version = pEntity.Version; + pDataContract.UdpUser = pEntity.UdpUser; + pDataContract.SystemEntryID = pEntity.SystemEntryID; + + pDataContract.Address1_Oid = pEntity.Address1_Oid; + pDataContract.Address1_Version = pEntity.Address1_Version; + pDataContract.Address2_Oid = pEntity.Address2_Oid; + pDataContract.Address2_Version = pEntity.Address2_Version; + + pDataContract.Distance_in_meter = pEntity.Distance_in_meter; + pDataContract.Time_in_sec = pEntity.Time_in_seconds; + + return pDataContract; + } + + public override AddressRoute MergeWithEntity(AddressRouteDC pDataContract, AddressRoute pEntity) + { + this.ConcurrencyCheck(pDataContract.Version, pEntity); + + pEntity.Oid = pDataContract.Oid; + pEntity.Notice = pDataContract.Notice; + pEntity.SystemEntryID = pDataContract.SystemEntryID; + + pEntity.Address1_Oid = pDataContract.Address1_Oid; + pEntity.Address1_Version = pDataContract.Address1_Version; + pEntity.Address2_Oid = pDataContract.Address2_Oid; + pEntity.Address2_Version = pDataContract.Address2_Version; + + pEntity.Distance_in_meter = pDataContract.Distance_in_meter; + pEntity.Time_in_seconds = pDataContract.Time_in_sec; + + return pEntity; + } + + protected override bool AreDCAndEntityEqual(AddressRouteDC pDC, AddressRoute pEntity) + { + if (pDC.Oid == null) + { + return false; + } + + return pDC.Oid == pEntity.Oid; + } + } +} diff --git a/Service/DCEntityMapper/MapperFactory.cs b/Service/DCEntityMapper/MapperFactory.cs index 76b3a0425..a34c246a7 100644 --- a/Service/DCEntityMapper/MapperFactory.cs +++ b/Service/DCEntityMapper/MapperFactory.cs @@ -288,6 +288,8 @@ namespace BeWo.Service.DCEntityMapper private static AbwesenheitsInformationPrintDC_AbwesenheitsInformationPrint _AbwesenheitsInformationPrintDC_AbwesenheitsInformationPrint; + private static AddressRouteDC_AddressRoute _AddressRouteDC_AddressRoute; + public static MedRecordDC_MedRecord MedRecordDC_MedRecord => _MedRecordDC_MedRecord ?? (_MedRecordDC_MedRecord = new MedRecordDC_MedRecord()); @@ -723,5 +725,8 @@ namespace BeWo.Service.DCEntityMapper public static AbwesenheitsInformationPrintDC_AbwesenheitsInformationPrint AbwesenheitsInformationPrintDC_AbwesenheitsInformationPrint => _AbwesenheitsInformationPrintDC_AbwesenheitsInformationPrint ?? (_AbwesenheitsInformationPrintDC_AbwesenheitsInformationPrint = new AbwesenheitsInformationPrintDC_AbwesenheitsInformationPrint()); + + public static AddressRouteDC_AddressRoute AddressRouteDC_AddressRoute => + _AddressRouteDC_AddressRoute ?? (_AddressRouteDC_AddressRoute = new AddressRouteDC_AddressRoute()); } } \ No newline at end of file diff --git a/Service/Service.csproj b/Service/Service.csproj index 9b3c3d27a..c96a08dc6 100644 --- a/Service/Service.csproj +++ b/Service/Service.csproj @@ -169,6 +169,7 @@ ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll @@ -218,6 +219,7 @@ + @@ -481,6 +483,8 @@ + + @@ -527,7 +531,6 @@ - diff --git a/Service/ServiceImplementations/OperationsServiceImp.cs b/Service/ServiceImplementations/OperationsServiceImp.cs index ac383f2dc..d797b1a38 100644 --- a/Service/ServiceImplementations/OperationsServiceImp.cs +++ b/Service/ServiceImplementations/OperationsServiceImp.cs @@ -15,6 +15,7 @@ using BeWo.Service.Plugins; using BeWo.Service.SBD; using BeWo.Service.Security; using BeWo.Service.ServiceContracts; +using BeWo.Service.ServiceUtils.Generell; using BeWo.Service.Vorlagen; using BS.Shared; using BS.Shared.Core; @@ -7265,5 +7266,23 @@ namespace BeWo.Service.ServiceImplementations DAOFactory.GenericDAO.Delete(signatures2Delete); } } + + public AddressRouteDC GetAddressRouteInfo(long adr1_oid, long adr1_ver, long adr2_oid, long adr2_ver) + { + try + { + var address1 = DAOFactory.GenericDAO.LoadByID
(adr1_oid); + var address2 = DAOFactory.GenericDAO.LoadByID
(adr2_oid); + + var res = AddressRouteManager.GetAddressRoute(address1, address2); + + return MapperFactory.AddressRouteDC_AddressRoute.MapToNewDC(res); + } + catch (Exception exception) + { + throw Utils.CreateBeWoFaultException(exception); + } + } + } } diff --git a/Service/ServiceUtils/API/GoogleDistanceMatrixAPI.cs b/Service/ServiceUtils/API/GoogleDistanceMatrixAPI.cs new file mode 100644 index 000000000..6b822ae80 --- /dev/null +++ b/Service/ServiceUtils/API/GoogleDistanceMatrixAPI.cs @@ -0,0 +1,106 @@ +using BeWo.Data.Entities; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using System.Web; + +namespace BeWo.Service.ServiceUtils.API +{ + public class GoogleDistanceMatrixApi + { + public class Response + { + public string Status { get; set; } + + [JsonProperty(PropertyName = "origin_addresses")] + public string[] OriginAddresses { get; set; } + + [JsonProperty(PropertyName = "destination_addresses")] + public string[] DestinationAddresses { get; set; } + + public Row[] Rows { get; set; } + + public class Data + { + public int Value { get; set; } + public string Text { get; set; } + } + + public class Element + { + public string Status { get; set; } + public Data Duration { get; set; } + public Data Distance { get; set; } + } + + public class Row + { + public Element[] Elements { get; set; } + } + } + + private string Key { get; set; } + private string Url { get; set; } + + private string[] OriginAddresses { get; set; } + private string[] DestinationAddresses { get; set; } + + public GoogleDistanceMatrixApi(Address originAddress, Address destinationAddress) : this(new string[] { originAddress.ToGoogle() }, new string[] { destinationAddress.ToGoogle() }) + { + + } + + public GoogleDistanceMatrixApi(string[] originAddresses, string[] destinationAddresses) + { + OriginAddresses = originAddresses; + DestinationAddresses = destinationAddresses; + + var appSettings = ConfigurationManager.AppSettings; + + if (string.IsNullOrEmpty(appSettings["GoogleDistanceMatrixApiUrl"])) + { + throw new Exception("GoogleDistanceMatrixApiUrl is not set in AppSettings."); + } + Url = appSettings["GoogleDistanceMatrixApiUrl"]; + + if (string.IsNullOrEmpty(appSettings["GoogleDistanceMatrixApiKey"])) + { + throw new Exception("GoogleDistanceMatrixApiKey is not set in AppSettings."); + } + Key = appSettings["GoogleDistanceMatrixApiKey"]; + } + + public async Task GetResponse() + { + using (var client = new HttpClient()) + { + var uri = new Uri(GetRequestUrl()); + + HttpResponseMessage response = await client.GetAsync(uri); + if (!response.IsSuccessStatusCode) + { + throw new Exception("GoogleDistanceMatrixApi failed with status code: " + response.StatusCode); + } + else + { + var content = await response.Content.ReadAsStringAsync(); + return JsonConvert.DeserializeObject(content); + } + } + } + + private string GetRequestUrl() + { + OriginAddresses = OriginAddresses.Select(HttpUtility.UrlEncode).ToArray(); + var origins = string.Join("|", OriginAddresses); + DestinationAddresses = DestinationAddresses.Select(HttpUtility.UrlEncode).ToArray(); + var destinations = string.Join("|", DestinationAddresses); + return $"{Url}?origins={origins}&destinations={destinations}&key={Key}"; + } + } +} diff --git a/Service/ServiceUtils/Generell/AddressRouteManager.cs b/Service/ServiceUtils/Generell/AddressRouteManager.cs new file mode 100644 index 000000000..91f3ceaa3 --- /dev/null +++ b/Service/ServiceUtils/Generell/AddressRouteManager.cs @@ -0,0 +1,95 @@ +using BeWo.Data.Access; +using BeWo.Data.Entities; +using BeWo.Service.DCEntityMapper; +using BeWo.Service.ServiceUtils.API; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BeWo.Service.ServiceUtils.Generell +{ + public static class AddressRouteManager + { + public static AddressRoute GetAddressRoute(Address address1, Address address2) + { + var routes = DAOFactory.GenericDAO.GetAll(); + + foreach (var route in routes) + { + if (route.Address1_Oid == address1.Oid && route.Address2_Oid == address2.Oid) + { + if (route.Address1_Version == address1.Version && route.Address2_Version == address2.Version) + { + // Route korrekt vorhanden + return route; + } + else + { + // Route vorhanden, aber Addresse hat update + return UpdateAddressRoute(route, address1, address2); + } + } + } + + // Route nicht vorhanden + return InsertNewAddressRoute(address1, address2); + } + + public static void DeleteAddressRoute(long oid) => DeleteAddressRoute(DAOFactory.GenericDAO.LoadByID(oid)); + + public static void DeleteAddressRoute(AddressRoute route) + { + if (route is object) + DAOFactory.GenericDAO.Delete(route); + } + + public static AddressRoute InsertNewAddressRoute(Address address1, Address address2) + { + var newRoute = new AddressRoute + { + Address1_Oid = address1.Oid.Value, + Address2_Oid = address2.Oid.Value + }; + + RequestAddressRoute(ref newRoute, address1, address2); + + DAOFactory.GenericDAO.Insert(newRoute); + + return newRoute; + } + + public static AddressRoute UpdateAddressRoute(AddressRoute route, Address address1, Address address2) + { + RequestAddressRoute(ref route, address1, address2); + + DAOFactory.GenericDAO.Update(route); + + return route; + } + + public static AddressRoute RequestAddressRoute(ref AddressRoute route, Address address1, Address address2) + { + route.Address1_Version = address1.Version.Value; + route.Address2_Version = address2.Version.Value; + + // Calculate Distance + + var api = new GoogleDistanceMatrixApi(address1, address2); + var task = api.GetResponse(); + + task.Wait(); + + if(task.Exception is object) + { + throw task.Exception; + } + + route.Distance_in_meter = task.Result.Rows[0].Elements[0].Distance.Value; + route.Time_in_seconds = task.Result.Rows[0].Elements[0].Duration.Value; + + return route; + } + } +} diff --git a/Shared/BeWoEntityEnums.cs b/Shared/BeWoEntityEnums.cs index 5de0154e2..24b9bdc03 100644 --- a/Shared/BeWoEntityEnums.cs +++ b/Shared/BeWoEntityEnums.cs @@ -160,7 +160,8 @@ namespace BS.Shared RegelmaessigerDienst = 153, GeschenkterUrlaubstag = 154, Preis = 155, - AbwesenheitsInformationPrint = 156 + AbwesenheitsInformationPrint = 156, + AddressRoute = 160 } public enum SystemEntryID diff --git a/Shared/DataContracts/AddressRouteDC.cs b/Shared/DataContracts/AddressRouteDC.cs new file mode 100644 index 000000000..602ae8b20 --- /dev/null +++ b/Shared/DataContracts/AddressRouteDC.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; + +namespace BS.Shared.DataContracts +{ + public class AddressRouteDC : IDataContract + { + [DataMember] + public long? Oid { get; set; } + + [DataMember] + public ActivationTypeId IsActive { get; set; } + + [DataMember] + public string Notice { get; set; } + + [DataMember] + public DateTime? InsTs { get; set; } + + [DataMember] + public string InsUser { get; set; } + + [DataMember] + public long? Version { get; set; } + + [DataMember] + public string UdpUser { get; set; } + + [DataMember] + public SystemEntryID? SystemEntryID { get; set; } + + [DataMember] + public long Address1_Oid { get; set; } + + [DataMember] + public long Address1_Version { get; set; } + + [DataMember] + public long Address2_Oid { get; set; } + + [DataMember] + public long Address2_Version { get; set; } + + [DataMember] + public int Distance_in_meter { get; set; } + + [DataMember] + public int Time_in_sec { get; set; } + + } +} diff --git a/Shared/Shared.csproj b/Shared/Shared.csproj index d0b386020..fdf8aaea0 100644 --- a/Shared/Shared.csproj +++ b/Shared/Shared.csproj @@ -154,6 +154,7 @@ +