diff --git a/CompControl.SapFrameworkConnector/App.config b/CompControl.SapFrameworkConnector/App.config new file mode 100644 index 0000000..e7094ce --- /dev/null +++ b/CompControl.SapFrameworkConnector/App.config @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CompControl.SapFrameworkConnector/CompControl.SapFrameworkConnector.csproj b/CompControl.SapFrameworkConnector/CompControl.SapFrameworkConnector.csproj new file mode 100644 index 0000000..1a78ebc --- /dev/null +++ b/CompControl.SapFrameworkConnector/CompControl.SapFrameworkConnector.csproj @@ -0,0 +1,145 @@ + + + + + Debug + AnyCPU + {236F375E-DEA1-461E-A05D-5358DCD25D09} + WinExe + CompControl.SapFrameworkConnector + CompControl.SapFrameworkConnector + v4.8 + 512 + true + true + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ExternalDLLs\CompControl.dll + + + ExternalDLLs\CompControl.ErpConnector.Service.dll + + + packages\log4net.3.2.0\lib\net462\log4net.dll + + + packages\Microsoft.Owin.4.2.3\lib\net45\Microsoft.Owin.dll + + + packages\Microsoft.Owin.Host.HttpListener.4.2.3\lib\net45\Microsoft.Owin.Host.HttpListener.dll + + + packages\Microsoft.Owin.Hosting.4.2.3\lib\net45\Microsoft.Owin.Hosting.dll + + + packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll + + + packages\Newtonsoft.Json.Bson.1.0.2\lib\net45\Newtonsoft.Json.Bson.dll + + + packages\Owin.1.0\lib\net40\Owin.dll + + + ExternalDLLs\sapnco.dll + + + ExternalDLLs\sapnco_utils.dll + + + + packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + + + + + packages\System.Memory.4.5.5\lib\net461\System.Memory.dll + + + packages\Microsoft.AspNet.WebApi.Client.6.0.0\lib\net45\System.Net.Http.Formatting.dll + + + + packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + + + + packages\Microsoft.AspNet.WebApi.Core.5.3.0\lib\net45\System.Web.Http.dll + + + packages\Microsoft.AspNet.WebApi.Owin.5.3.0\lib\net45\System.Web.Http.Owin.dll + + + + + + + + + + + + + + Component + + + ProjectInstaller.cs + + + + + Component + + + Service.cs + + + + + + + + + + + + + ProjectInstaller.cs + + + Service.cs + + + + + \ No newline at end of file diff --git a/CompControl.SapFrameworkConnector/CompControl.SapFrameworkConnector.sln b/CompControl.SapFrameworkConnector/CompControl.SapFrameworkConnector.sln new file mode 100644 index 0000000..e007a68 --- /dev/null +++ b/CompControl.SapFrameworkConnector/CompControl.SapFrameworkConnector.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35728.132 d17.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CompControl.SapFrameworkConnector", "CompControl.SapFrameworkConnector.csproj", "{236F375E-DEA1-461E-A05D-5358DCD25D09}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {236F375E-DEA1-461E-A05D-5358DCD25D09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {236F375E-DEA1-461E-A05D-5358DCD25D09}.Debug|Any CPU.Build.0 = Debug|Any CPU + {236F375E-DEA1-461E-A05D-5358DCD25D09}.Release|Any CPU.ActiveCfg = Release|Any CPU + {236F375E-DEA1-461E-A05D-5358DCD25D09}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/CompControl.SapFrameworkConnector/ConfigHelper.cs b/CompControl.SapFrameworkConnector/ConfigHelper.cs new file mode 100644 index 0000000..5765cd1 --- /dev/null +++ b/CompControl.SapFrameworkConnector/ConfigHelper.cs @@ -0,0 +1,19 @@ +using System; +using System.Configuration; + +namespace CompControl.SapFrameworkConnector +{ + public class ConfigHelper + { + public static readonly string ThisWebApiServiceEndpoint = ConfigurationManager.AppSettings["ThisWebApiServiceEndpoint"]; + public static readonly string ActiveSapDestinationName = ConfigurationManager.AppSettings["ActiveSapDestinationName"]; + public static readonly string SapDefaultUSER = ConfigurationManager.AppSettings["SapDefaultUSER"]; + public static readonly string SapDefaultPASSWD = ConfigurationManager.AppSettings["SapDefaultPASSWD"]; + public static readonly string SapCLIENT = ConfigurationManager.AppSettings["SapCLIENT"]; + public static readonly string SapLanguage = ConfigurationManager.AppSettings["SapLanguage"]; + public static readonly string SapASHOST = ConfigurationManager.AppSettings["SapASHOST"]; + public static readonly string SapSYSNR = ConfigurationManager.AppSettings["SapSYSNR"]; + public static readonly string SapMaxPoolSize = ConfigurationManager.AppSettings["SapMaxPoolSize"]; + public static readonly string SapIdleTimeout = ConfigurationManager.AppSettings["SapIdleTimeout"]; + } +} diff --git a/CompControl.SapFrameworkConnector/ExternalDLLs/CompControl.ErpConnector.Service.dll b/CompControl.SapFrameworkConnector/ExternalDLLs/CompControl.ErpConnector.Service.dll new file mode 100644 index 0000000..8cd7a93 Binary files /dev/null and b/CompControl.SapFrameworkConnector/ExternalDLLs/CompControl.ErpConnector.Service.dll differ diff --git a/CompControl.SapFrameworkConnector/ExternalDLLs/CompControl.dll b/CompControl.SapFrameworkConnector/ExternalDLLs/CompControl.dll new file mode 100644 index 0000000..b7f9a47 Binary files /dev/null and b/CompControl.SapFrameworkConnector/ExternalDLLs/CompControl.dll differ diff --git a/CompControl.SapFrameworkConnector/ExternalDLLs/sapnco.dll b/CompControl.SapFrameworkConnector/ExternalDLLs/sapnco.dll new file mode 100644 index 0000000..61bb9a3 Binary files /dev/null and b/CompControl.SapFrameworkConnector/ExternalDLLs/sapnco.dll differ diff --git a/CompControl.SapFrameworkConnector/ExternalDLLs/sapnco_utils.dll b/CompControl.SapFrameworkConnector/ExternalDLLs/sapnco_utils.dll new file mode 100644 index 0000000..9c65d6c Binary files /dev/null and b/CompControl.SapFrameworkConnector/ExternalDLLs/sapnco_utils.dll differ diff --git a/CompControl.SapFrameworkConnector/GBS/GBSApiController.cs b/CompControl.SapFrameworkConnector/GBS/GBSApiController.cs new file mode 100644 index 0000000..21b1a1a --- /dev/null +++ b/CompControl.SapFrameworkConnector/GBS/GBSApiController.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Web.Http; + +namespace CompControl.SapFrameworkConnector +{ + [RoutePrefix("api/gbs")] + public class GBSApiController + { + private static readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + } +} diff --git a/CompControl.SapFrameworkConnector/Program.cs b/CompControl.SapFrameworkConnector/Program.cs new file mode 100644 index 0000000..63cc98d --- /dev/null +++ b/CompControl.SapFrameworkConnector/Program.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.ServiceProcess; +using System.Text; +using System.Threading.Tasks; + +namespace CompControl.SapFrameworkConnector +{ + internal static class Program + { + /// + /// The main entry point for the application. + /// + static void Main() + { + ServiceBase[] ServicesToRun; + ServicesToRun = new ServiceBase[] + { + new Service() + }; + ServiceBase.Run(ServicesToRun); + } + } +} diff --git a/CompControl.SapFrameworkConnector/ProjectInstaller.Designer.cs b/CompControl.SapFrameworkConnector/ProjectInstaller.Designer.cs new file mode 100644 index 0000000..6944bfa --- /dev/null +++ b/CompControl.SapFrameworkConnector/ProjectInstaller.Designer.cs @@ -0,0 +1,66 @@ +using System.Configuration.Install; + +namespace CompControl.SapFrameworkConnector +{ + partial class ProjectInstaller + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller(); + this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller(); + + // serviceProcessInstaller1 + this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem; + this.serviceProcessInstaller1.Password = null; + this.serviceProcessInstaller1.Username = null; + + // serviceInstaller1 + this.serviceInstaller1.DelayedAutoStart = true; + this.serviceInstaller1.Description = "CompControl SapFrameworkConnector"; + this.serviceInstaller1.ServiceName = "CompControl.SapFrameworkConnector"; + this.serviceInstaller1.DisplayName = this.serviceInstaller1.ServiceName; + this.serviceInstaller1.ServicesDependedOn = new string[] { "" }; + this.serviceInstaller1.AfterInstall += new System.Configuration.Install.InstallEventHandler(this.serviceInstaller1_AfterInstall); + + // ProjectInstaller + this.Installers.AddRange(new System.Configuration.Install.Installer[] { + this.serviceProcessInstaller1, + this.serviceInstaller1}); + + } + + #endregion + + private System.ServiceProcess.ServiceProcessInstaller serviceProcessInstaller1; + private System.ServiceProcess.ServiceInstaller serviceInstaller1; + + private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e) + { + + } + } +} \ No newline at end of file diff --git a/CompControl.SapFrameworkConnector/ProjectInstaller.cs b/CompControl.SapFrameworkConnector/ProjectInstaller.cs new file mode 100644 index 0000000..85112c1 --- /dev/null +++ b/CompControl.SapFrameworkConnector/ProjectInstaller.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Configuration.Install; +using System.Linq; +using System.Threading.Tasks; + +namespace CompControl.SapFrameworkConnector +{ + [RunInstaller(true)] + public partial class ProjectInstaller : System.Configuration.Install.Installer + { + public ProjectInstaller() + { + InitializeComponent(); + } + } +} diff --git a/CompControl.SapFrameworkConnector/ProjectInstaller.resx b/CompControl.SapFrameworkConnector/ProjectInstaller.resx new file mode 100644 index 0000000..efe3a56 --- /dev/null +++ b/CompControl.SapFrameworkConnector/ProjectInstaller.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 227, 17 + + + False + + \ No newline at end of file diff --git a/CompControl.SapFrameworkConnector/Properties/AssemblyInfo.cs b/CompControl.SapFrameworkConnector/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..9192e21 --- /dev/null +++ b/CompControl.SapFrameworkConnector/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("CompControl.SapFrameworkConnector")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("CompControl.SapFrameworkConnector")] +[assembly: AssemblyCopyright("Copyright © 2025")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("236f375e-dea1-461e-a05d-5358dcd25d09")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/CompControl.SapFrameworkConnector/Service.Designer.cs b/CompControl.SapFrameworkConnector/Service.Designer.cs new file mode 100644 index 0000000..71823b5 --- /dev/null +++ b/CompControl.SapFrameworkConnector/Service.Designer.cs @@ -0,0 +1,36 @@ +namespace CompControl.SapFrameworkConnector +{ + partial class Service + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.ServiceName = "CompControl.SapFrameworkConnector"; + } + + #endregion + } +} diff --git a/CompControl.SapFrameworkConnector/Service.cs b/CompControl.SapFrameworkConnector/Service.cs new file mode 100644 index 0000000..0672792 --- /dev/null +++ b/CompControl.SapFrameworkConnector/Service.cs @@ -0,0 +1,65 @@ +using CompControl.SapFrameworkConnector; +using Microsoft.Owin; +using Microsoft.Owin.Hosting; +using SAP.Middleware.Connector; +using System; +using System.Configuration; +using System.ServiceProcess; +using System.Xml; + +namespace CompControl.SapFrameworkConnector +{ + public partial class Service : ServiceBase + { + private static readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + private IDisposable _server = null; + + + public Service() + { + InitializeComponent(); + } + + protected override void OnStart(string[] args) + { + RfcTrace.DefaultTraceLevel = 3; + RfcTrace.TraceDirectory = @"C:\Temp\CC\NCoLogs"; // Log-Dateien in diesem Ordner speichern + _log.Debug("SAP NCo Logging aktiviert: " + RfcTrace.TraceDirectory); + + var config = new ConfigFileDestination(); + if (!RfcDestinationManager.IsDestinationConfigurationRegistered()) { RfcDestinationManager.RegisterDestinationConfiguration(config); } + var dest = RfcDestinationManager.GetDestination(ConfigHelper.ActiveSapDestinationName); // Jetzt kannst du die Destination abrufen + _log.Info("SAP Destination loaded: " + dest.Name); + + _server = WebApp.Start(url: ConfigHelper.ThisWebApiServiceEndpoint); + _log.Info($"Service started successfully at: {ConfigHelper.ThisWebApiServiceEndpoint}"); + } + + protected override void OnStop() + { + _log.Debug($"Service was stopped!"); + } + + } +} + +public class ConfigFileDestination : IDestinationConfiguration +{ + private static readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public RfcConfigParameters GetParameters(string destinationName) + { + RfcConfigParameters parms = new RfcConfigParameters(); + parms.Add(RfcConfigParameters.AppServerHost, ConfigHelper.SapASHOST); + parms.Add(RfcConfigParameters.SystemNumber, ConfigHelper.SapSYSNR); + parms.Add(RfcConfigParameters.Client, ConfigHelper.SapCLIENT); + parms.Add(RfcConfigParameters.User, ConfigHelper.SapDefaultUSER); + parms.Add(RfcConfigParameters.Password, ConfigHelper.SapDefaultPASSWD); + parms.Add(RfcConfigParameters.Language, ConfigHelper.SapLanguage); + _log.Debug($"Destination registered => ASHOST={ConfigHelper.SapASHOST} | SYSNR={ConfigHelper.SapSYSNR} | CLIENT={ConfigHelper.SapCLIENT} | USER={ConfigHelper.SapDefaultUSER} | LANG={ConfigHelper.SapLanguage}"); + return parms; + } + + public bool ChangeEventsSupported() => false; + public event RfcDestinationManager.ConfigurationChangeHandler ConfigurationChanged; +} \ No newline at end of file diff --git a/CompControl.SapFrameworkConnector/Service.resx b/CompControl.SapFrameworkConnector/Service.resx new file mode 100644 index 0000000..e5858cc --- /dev/null +++ b/CompControl.SapFrameworkConnector/Service.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + False + + \ No newline at end of file diff --git a/CompControl.SapFrameworkConnector/ServiceController.cs b/CompControl.SapFrameworkConnector/ServiceController.cs new file mode 100644 index 0000000..0fd8a59 --- /dev/null +++ b/CompControl.SapFrameworkConnector/ServiceController.cs @@ -0,0 +1,22 @@ +using System.Net; +using System.Net.Http; +using System.Web.Http; + +namespace CompControl.SapFrameworkConnector +{ + [RoutePrefix("api/service")] + public class ServiceController : ApiController + { + private static readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + #region Ping + // GET api/service/ping + [Route("ping")] + [HttpGet] + public HttpResponseMessage Ping() + { + return Request.CreateResponse(HttpStatusCode.OK, true); + } + #endregion + } +} diff --git a/CompControl.SapFrameworkConnector/Standard/SapStandardFunctions.cs b/CompControl.SapFrameworkConnector/Standard/SapStandardFunctions.cs new file mode 100644 index 0000000..7e54996 --- /dev/null +++ b/CompControl.SapFrameworkConnector/Standard/SapStandardFunctions.cs @@ -0,0 +1,261 @@ +using log4net; +using SAP.Middleware.Connector; +using System; +using System.Collections.Generic; +using static CompControl.ErpConnector.Service.Models.Cicor_SapModels; +using static CompControl.ErpConnector.Service.Models.SapDataTypes; + +namespace CompControl.SapFrameworkConnector +{ + public class SapStandardFunctions + { + private static readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); //Logger + + + //----------------------------------------------------------------------------------------------------------------------------------------------------------------------- + + public static DateTime ConvertSapDateToDateTime(string sapDate, bool delimitersUsed = true) + { + if (delimitersUsed) //Style: 2022-02-18, mostly gotten from SAP with GetString on DATS + { + int year = Convert.ToInt32(sapDate.Substring(0, 4)); + int month = Convert.ToInt32(sapDate.Substring(5, 2)); + int day = Convert.ToInt32(sapDate.Substring(8, 2)); + return new DateTime(year, month, day); + } + else //Style: 20220218 (Like stored in SAP, needed for input) + { + int year = Convert.ToInt32(sapDate.Substring(0, 4)); + int month = Convert.ToInt32(sapDate.Substring(4, 2)); + int day = Convert.ToInt32(sapDate.Substring(6, 2)); + return new DateTime(year, month, day); + } + } + public static string ConvertDateTimeToSapTime(DateTime date) + { + if (date == null) { return "00000000"; } + return date.ToString("yyyyMMdd"); + } + public static string ConvertMslToSAPString(string matfeuchte) + { + if (matfeuchte == null || matfeuchte.Equals("")) { return "01"; } + switch (matfeuchte) + { + case "0": + return "01"; + case "1": + return "01"; + case "2": + return "02"; + case "3": + return "03"; + case "4": + return "04"; + case "5": + return "05"; + case "6": + return "06"; + case "2a": + return "07"; + case "5a": + return "08"; + default: + return "01"; + } + } + + //----------------------------------------------------------------------------------------------------------------------------------------------------------------------- + + public static GetMATNRfromBMATN_EXPORT GetMATNRfromBMATN(GetMATNRfromBMATN_IMPORT import) + { + string errorMsg = ""; + GetMATNRfromBMATN_EXPORT export = new GetMATNRfromBMATN_EXPORT(); + + try + { + RfcDestination dest = RfcDestinationManager.GetDestination(ConfigHelper.ActiveSapDestinationName); + IRfcFunction func = dest.Repository.CreateFunction("RFC_READ_TABLE"); //Create Function + IRfcTable t2 = func.GetTable("DATA"); + t2.Clear(); + IRfcTable options2 = func.GetTable("OPTIONS"); + options2.Clear(); + options2.Append(); + options2.SetValue("TEXT", "BMATN = '" + import.BMATN?.Trim().PadLeft(18, '0') + "'"); + IRfcTable fields2 = func.GetTable("FIELDS"); + fields2.Append(1); + fields2.CurrentIndex = 0; fields2.SetValue(0, "EMATN"); + func.SetValue("QUERY_TABLE", "AMPL"); //Set Value to function + func.SetValue("DELIMITER", ";"); //Set Value to function + func.SetValue("USE_ET_DATA_4_RETURN", "0"); + func.Invoke(dest); //Invoke function at Sap destination + + IRfcTable rfcTable2 = func.GetTable("DATA"); //Process return values + _log.Debug("Number rows DATA of MATNR found: " + rfcTable2.Count); + int rowCount2 = rfcTable2.Count; + + foreach (IRfcStructure structure in rfcTable2) + { + export.MATNR = structure.GetString(0); + _log.Debug("MATNR received: " + export.MATNR); + } + } + catch (Exception ex) { errorMsg += "CI: SAP Other Exception: " + ex; } + + if (!errorMsg.Equals("")) { _log.Error(errorMsg); } + + return export; + } + public static GetMAKTXfromMATNR_EXPORT GetMAKTXfromMATNR(GetMAKTXfromMATNR_IMPORT import) + { + string errorMsg = ""; + GetMAKTXfromMATNR_EXPORT export = new GetMAKTXfromMATNR_EXPORT(); + + try + { + RfcDestination dest = RfcDestinationManager.GetDestination(ConfigHelper.ActiveSapDestinationName); + IRfcFunction func3 = dest.Repository.CreateFunction("RFC_READ_TABLE"); //Create Function + IRfcTable t3 = func3.GetTable("DATA"); + t3.Clear(); + IRfcTable options3 = func3.GetTable("OPTIONS"); + options3.Clear(); + options3.Append(); + options3.SetValue("TEXT", "MATNR = '" + import.MATNR?.Trim().PadLeft(18, '0') + "'"); + options3.Append(); + IRfcTable fields3 = func3.GetTable("FIELDS"); + fields3.Append(1); + fields3.CurrentIndex = 0; fields3.SetValue(0, "MAKTX"); + func3.SetValue("QUERY_TABLE", "MAKT"); + func3.SetValue("DELIMITER", ";"); + func3.SetValue("USE_ET_DATA_4_RETURN", "0"); + func3.Invoke(dest); //Invoke function at Sap destination + + IRfcTable rfcTable3 = func3.GetTable("DATA"); //Process return values + _log.Debug("Number rows DATA of MAKTX found: " + rfcTable3.Count); + int rowCount3 = rfcTable3.Count; + + foreach (IRfcStructure structure in rfcTable3) + { + export.MAKTX = structure.GetString(0); + _log.Info("MAKTX received: " + export.MAKTX); + } + } + catch (Exception ex) { errorMsg += "CI: SAP Other Exception: " + ex; } + + if (!errorMsg.Equals("")) { _log.Error(errorMsg); } + + _log.Debug($"GetMAKTXforMATNR: Found MAKTX for MATNR {import.MATNR}: {export.MAKTX}"); + + return export; + } + + public static BAPI_PO_GETDETAIL_EXPORT BAPI_PO_GETDETAILS(BAPI_PO_GETDETAIL_IMPORT import) + { + string errorMsg = ""; + BAPI_PO_GETDETAIL_EXPORT export = new BAPI_PO_GETDETAIL_EXPORT(); + List poItemBuffer = new List(); + + + if (import != null) + { + try + { + RfcDestination dest = RfcDestinationManager.GetDestination(ConfigHelper.ActiveSapDestinationName); + IRfcFunction func = dest.Repository.CreateFunction("BAPI_PO_GETDETAIL"); //Create Function + func.SetValue("PURCHASEORDER", import.PURCHASEORDER?.Trim().PadLeft(10, '0')); //Set Value to function + func.SetValue("ITEMS", import.ITEMS); //Set Value to function + func.SetValue("HISTORY", "X"); + func.SetValue("SCHEDULES", "X"); + func.SetValue("ACCOUNT_ASSIGNMENT", "X"); + func.SetValue("ITEM_TEXTS", "X"); + func.SetValue("HEADER_TEXTS", "X"); + func.SetValue("SERVICES", "X"); + func.SetValue("CONFIRMATIONS", "X"); + func.SetValue("SERVICE_TEXTS", "X"); + func.SetValue("EXTENSIONS", "X"); + func.Invoke(dest); //Invoke function at Sap destination + + IRfcStructure po_header_struct = func.GetStructure("PO_HEADER"); + export.PO_HEADER.PO_NUMBER = po_header_struct.GetString("PO_NUMBER"); + export.PO_HEADER.CREATED_ON = po_header_struct.GetString("CREATED_ON"); + export.PO_HEADER.CREATED_BY = po_header_struct.GetString("CREATED_BY"); + export.PO_HEADER.DOC_TYPE = po_header_struct.GetString("DOC_TYPE"); + export.PO_HEADER.VENDOR = po_header_struct.GetString("VENDOR"); + export.PO_HEADER.VEND_NAME = po_header_struct.GetString("VEND_NAME"); + if (!(export.PO_HEADER.DOC_TYPE.Equals("MP") || export.PO_HEADER.DOC_TYPE.Equals("MP") || export.PO_HEADER.DOC_TYPE.Equals("MP") || export.PO_HEADER.DOC_TYPE.Equals("ZBRO"))) { } + + IRfcTable po_items_table = func.GetTable("PO_ITEMS"); + foreach (IRfcStructure row in po_items_table) + { + BAPIEKPO temp = new BAPIEKPO(); + temp.PO_NUMBER = row.GetString("PO_NUMBER").TrimStart('0') ?? ""; + temp.PO_ITEM = row.GetString("PO_ITEM").TrimStart('0') ?? ""; + temp.STATUS = row.GetString("STATUS") ?? ""; + temp.CHANGED_ON = row.GetString("CHANGED_ON") ?? ""; + temp.SHORT_TEXT = row.GetString("SHORT_TEXT") ?? ""; + temp.MATERIAL = row.GetString("MATERIAL").TrimStart('0') ?? ""; + temp.PUR_MAT = row.GetString("PUR_MAT").TrimStart('0') ?? ""; + temp.QUANTITY = row.GetDecimal("QUANTITY"); + temp.UNIT = row.GetString("UNIT") ?? ""; + temp.PLANT = row.GetString("PLANT") ?? ""; + temp.MAT_GRP = row.GetString("MAT_GRP") ?? ""; + temp.ACCTASSCAT = row.GetString("ACCTASSCAT") ?? ""; + temp.QUAL_INSP = row.GetString("QUAL_INSP") ?? ""; + temp.MANU_MAT = row.GetString("MANU_MAT") ?? ""; + temp.MFR_NO = row.GetString("MFR_NO") ?? ""; + temp.VEND_MAT = row.GetString("VEND_MAT") ?? ""; + temp.STOR_LOC = row.GetString("STORE_LOC") ?? ""; + temp.DELETE_IND = row.GetString("DELETE_IND") ?? ""; + poItemBuffer.Add(temp); + } + + IRfcTable po_item_hist_total = func.GetTable("PO_ITEM_HISTORY_TOTALS"); + foreach (IRfcStructure row in po_item_hist_total) + { + BAPIEKBES temp = new BAPIEKBES(); + temp.BLOCKED_QY = row.GetDecimal("BLOCKED_QY"); + temp.BL_QTY = row.GetDecimal("BL_QTY"); + temp.BL_QTY_TOTAL = row.GetDecimal("BL_QTY_TOTAL"); + temp.DELIV_QTY = row.GetDecimal("DELIV_QTY"); + temp.DL_QTY_TOTAL = row.GetDecimal("DL_QTY_TOTAL"); + temp.DL_QTY_TRSP = row.GetDecimal("DL_QTY_TRSP"); + temp.IV_QTY = row.GetDecimal("IV_QTY"); + temp.IV_QTY_TOTAL = row.GetDecimal("IV_QTY_TOTAL"); + temp.PO_ITEM = row.GetString("PO_ITEM").TrimStart('0') ?? ""; + temp.PO_PR_QNT = row.GetDecimal("PO_PR_QNT"); + temp.SERIAL_NO = row.GetString("SERIAL_NO").TrimStart('0') ?? ""; + temp.WITHDR_QTY = row.GetDecimal("WITHDR_QTY"); + export.PO_ITEM_HISTORY_TOTAL.Add(temp); + } + + IRfcTable po_item_hist = func.GetTable("PO_ITEM_HISTORY"); + foreach (IRfcStructure row in po_item_hist) + { + BAPIEKBE temp = new BAPIEKBE(); + temp.BATCH = row.GetString("BATCH") ?? ""; + temp.DOC_YEAR = row.GetString("DOC_YEAR") ?? ""; + temp.MATDOC_ITM = row.GetString("MATDOC_ITM") ?? ""; + temp.MATERIAL = row.GetString("MATERIAL") ?? ""; + temp.MAT_DOC = row.GetString("MAT_DOC") ?? ""; + temp.MOVE_TYPE = row.GetString("MOVE_TYPE") ?? ""; + temp.PO_ITEM = row.GetString("PO_ITEM") ?? ""; + temp.PROCESS_ID = row.GetString("PROCESS_ID") ?? ""; + temp.PSTNG_DATE = row.GetString("PSTNG_DATE") ?? ""; + temp.PUR_MAT = row.GetString("PUR_MAT") ?? ""; + temp.QUANTITY = row.GetDecimal("QUANTITY"); + temp.REF_DOC_NO = row.GetString("REF_DOC_NO") ?? ""; + temp.SERIAL_NO = row.GetString("SERIAL_NO") ?? ""; + temp.DELIV_QTY = row.GetDecimal("DELIV_QTY"); + temp.DELIV_UNIT = row.GetString("DELIV_UNIT") ?? ""; + export.PO_ITEM_HISTORY.Add(temp); + } + } + catch (Exception ex) { errorMsg += "CI: SAP Other Exception: " + ex; } + } + else { _log.Debug("Error, IMPORT for BAPI_PO_GETDETAILS was NULL! "); } + + if (!errorMsg.Equals("")) { _log.Debug(errorMsg); } + + return export; + } + } +} diff --git a/CompControl.SapFrameworkConnector/Standard/StandardApiController.cs b/CompControl.SapFrameworkConnector/Standard/StandardApiController.cs new file mode 100644 index 0000000..0944928 --- /dev/null +++ b/CompControl.SapFrameworkConnector/Standard/StandardApiController.cs @@ -0,0 +1,141 @@ +using System; +using System.Net.Http; +using System.Net; +using System.Threading; +using System.Threading.Tasks; +using System.Web.Http; +using CompControl.ErpConnector.Service.Models; +using static CompControl.ErpConnector.Service.Models.Cicor_SapModels; +using static CompControl.ErpConnector.Service.Models.SapDataTypes; + + +namespace CompControl.SapFrameworkConnector +{ + [RoutePrefix("api/we")] + public class StandardApiController: ApiController + { + private static readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + [Route("getbestellungen")] + [HttpPut] + public async Task GetBestellungen([FromBody] FilterBestellungen filterBestellungen, CancellationToken cancellationToken) + { + ApiResultBestellungen result = new ApiResultBestellungen(); //New ApiResult to return via Web + + try + { + _log.Debug("GetBestellungen received for Filter: " + filterBestellungen.ToString()); + + BAPI_PO_GETDETAIL_IMPORT import = new BAPI_PO_GETDETAIL_IMPORT() { PURCHASEORDER = filterBestellungen.OrderNo }; + BAPI_PO_GETDETAIL_EXPORT details = SapStandardFunctions.BAPI_PO_GETDETAILS(import); + int cnt = 0; + + foreach (BAPIEKPO det in details.PO_ITEMS) + { + cnt++; + string inspect = ""; + string inspectInfo = ""; + string prioText = ""; + string prioChar = ""; + string ItemText1 = ""; + bool posIsClosed = false; + DateTime expDeliverDate = DateTime.MaxValue; + + if (det.QUAL_INSP.Equals("X")) + { + inspect = "Q"; + if (ConfigHelper.SapLanguage.Equals("DE")) { inspectInfo = "Qualitaetspruefung erforderlich!"; } + else { inspectInfo = "Quality check mandatory!"; } + } + + expDeliverDate = SapStandardFunctions.ConvertSapDateToDateTime(det.ExpectedDeliveryDate, false); + if (det.QUANTITY <= det.QUANTITYPROCESSED) { posIsClosed = true; } + + GetMAKTXfromMATNR_IMPORT getMak = new GetMAKTXfromMATNR_IMPORT(); + getMak.MATNR = det.MATERIAL.Trim(); + GetMAKTXfromMATNR_EXPORT outMak = SapStandardFunctions.GetMAKTXfromMATNR(getMak); + ItemText1 = outMak.MAKTX; + + GrDataItem gr = new GrDataItem(); + gr.AcceptedManufacturesLink = cnt.ToString(); + gr.Created = SapStandardFunctions.ConvertSapDateToDateTime(details.PO_HEADER.CREATED_ON); + gr.LastUpdate = SapStandardFunctions.ConvertSapDateToDateTime(det.CHANGED_ON); + gr.PosIsClosed = posIsClosed; + gr.OrderNo = det.PO_NUMBER; + gr.OrderPos = det.PO_ITEM; + gr.OrderQuantity = det.QUANTITY; + gr.ItemNo = det.MATERIAL.Trim(); + gr.ItemText1 = ItemText1; + gr.ItemNoRef = gr.CustomValue05 = det.PUR_MAT; + gr.OrderPosInfoText = det.ACCTASSCAT; + gr.QuantityProcessed = det.QUANTITYPROCESSED; + gr.QuantityUnit = det.UNIT; + gr.Plant = det.PLANT; + gr.Inspection = inspect; + gr.InspectionInfo = inspectInfo; + gr.Priority = prioChar; + gr.PriorityInfoText = prioText; + gr.CustomValue01 = det.QUAL_INSP; + gr.ExpectedDeliveryDate = expDeliverDate; + gr.MPN = det.MANU_MAT.Trim(); + gr.SupplierNo = details.PO_HEADER.VENDOR; + gr.SupplierName = details.PO_HEADER.VEND_NAME; + gr.SupplierItemNo = det.VEND_MAT; + gr.StorageLocation = det.STOR_LOC; + gr.Schedule = det.SCHEDULE.TrimStart('0'); + gr.CustomValue08 = details.PO_HEADER.DOC_TYPE; + if (!det.DELETE_IND.Equals("L")) { result.GrDataItems.Add(gr); } + } + + _log.Debug($"Result of GetBestellungen now consists of {result.GrDataItems.Count} GrDataItems and {result.ManufacturerDataItems.Count} ManufactuerDataItems..."); + + if (result.IsSuccessful) { _log.Debug(result); } //Action was successful => log for debug + else { _log.Error(result); } //An error occurred + } + catch (Exception ex) + { + string sm = $"GetBestellungen: An unexpected error occured: " + ex; + _log.Error(sm); + result = new ApiResultBestellungen //ApiResult on Exception + { + ErrorNumber = 101, + MessageShort = sm, + MessageLong = sm, + MessageTechnical = $"{sm} [{filterBestellungen}] - {ex}" + }; + } + + return Request.CreateResponse(HttpStatusCode.OK, result); + } + + + [Route("getherstellerdaten")] + public async Task GetHerstellerdaten([FromUri] string itemNo, CancellationToken cancellationToken) + { + ApiResultHerstellerdaten result = new ApiResultHerstellerdaten(); //New ApiResult to return via Web + _log.Debug("GetHerstellerdaten received for itemNo: " + itemNo); + + try + { + + + if (result.IsSuccessful) { _log.Debug(result); } //Action was successful => log for debug + else { _log.Error(result); } //An error occurred + } + catch (Exception ex) + { + string sm = $"GetHerstellerDaten: An unexpected error occured for '{itemNo}' " + ex; + _log.Error(sm); + result = new ApiResultHerstellerdaten //Default ApiResult on error + { + ErrorNumber = 101, + MessageShort = sm, + MessageLong = sm, + MessageTechnical = $"{sm} [{itemNo}] - {ex}" + }; + } + + return Request.CreateResponse(HttpStatusCode.OK, result); + } + } +} diff --git a/CompControl.SapFrameworkConnector/Startup.cs b/CompControl.SapFrameworkConnector/Startup.cs new file mode 100644 index 0000000..1e6aa4d --- /dev/null +++ b/CompControl.SapFrameworkConnector/Startup.cs @@ -0,0 +1,95 @@ +using Owin; +using System.Web.Http.ExceptionHandling; +using System.Web.Http; +using Microsoft.Owin; +using System.Net.Http; +using System.Net; +using System.Threading.Tasks; +using System.Threading; +using System; + +[assembly: OwinStartup(typeof(CompControl.SapFrameworkConnector.Startup))] +[assembly: log4net.Config.XmlConfigurator(ConfigFile = "Log4Net.config", Watch = true)] + +namespace CompControl.SapFrameworkConnector +{ + public class Startup + { + public void Configuration(IAppBuilder app) + { + HttpConfiguration config = new HttpConfiguration(); + config.Services.Replace(typeof(IExceptionLogger), new UnhandledExceptionLogger()); + config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler()); + config.MapHttpAttributeRoutes(); + config.Routes.MapHttpRoute(name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional }); + app.UseWebApi(config); + } + } + + class UnhandledExceptionLogger : ExceptionLogger + { + private static readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + public override void Log(ExceptionLoggerContext context) { _log.Error("Web API - Unhandled Exception", context.Exception); } + } + + class GlobalExceptionHandler : ExceptionHandler + { + public override void Handle(ExceptionHandlerContext context) + { + if (context.Exception is ArgumentNullException) + { + var result = new HttpResponseMessage(HttpStatusCode.BadRequest) + { + Content = new StringContent(context.Exception.Message), + ReasonPhrase = "ArgumentNullException" + }; + + context.Result = new ArgumentNullResult(context.Request, result); + } + else + { + // Handle other exceptions + context.Result = new TextPlainErrorResult + { + Request = context.ExceptionContext.Request, + Content = context.Exception.Message, + ReasonPhrase = "Unhandled Web API Exception" + }; + } + } + + private class TextPlainErrorResult : IHttpActionResult + { + public HttpRequestMessage Request { get; set; } + public string Content { get; set; } + public string ReasonPhrase { get; set; } + + public Task ExecuteAsync(CancellationToken cancellationToken) + { + HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.InternalServerError); + response.Content = new StringContent(Content); + response.RequestMessage = Request; + response.ReasonPhrase = ReasonPhrase; + return Task.FromResult(response); + } + } + + private class ArgumentNullResult : IHttpActionResult + { + private HttpRequestMessage _request; + private HttpResponseMessage _httpResponseMessage; + + + public ArgumentNullResult(HttpRequestMessage request, HttpResponseMessage httpResponseMessage) + { + _request = request; + _httpResponseMessage = httpResponseMessage; + } + + public Task ExecuteAsync(CancellationToken cancellationToken) + { + return Task.FromResult(_httpResponseMessage); + } + } + } +} diff --git a/CompControl.SapFrameworkConnector/packages.config b/CompControl.SapFrameworkConnector/packages.config new file mode 100644 index 0000000..09a5b87 --- /dev/null +++ b/CompControl.SapFrameworkConnector/packages.config @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file