using CompControl.ErpConnector.Utility.Models;
using SAP.Middleware.Connector;
using System;
using System.Collections.Generic;
using System.Text;
using static CompControl.ErpConnector.Utility.Models.SAP_CompControl_Models;
using static CompControl.ErpConnector.Utility.Models.SAP_BAPI_Models;
using System.Threading;

namespace CompControl.SapFrameworkConnector
{
    public class SapStandardFunctions
    {
        private static readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); //Logger


        public static ApiResultBestellungen GetBestellung(string poNo, bool useDetailsAlternative = false)
        {
            ApiResultBestellungen result = new ApiResultBestellungen();
            BAPI_PO_GETDETAIL_IMPORT import = new BAPI_PO_GETDETAIL_IMPORT() { PURCHASEORDER = poNo, ITEMS = "X" };
            BAPI_PO_GETDETAIL_EXPORT details = new BAPI_PO_GETDETAIL_EXPORT();
            if (useDetailsAlternative) { details = BAPI_PO_GETDETAILS1(import); _log.Debug($"using BAPI_PO_GETDETAILS-1 !!!"); }
            else { details = BAPI_PO_GETDETAILS(import); _log.Debug($"using BAPI_PO_GETDETAILS"); }

            _log.Debug($"PO_RET => {details.PO_ITEM_HISTORY.Count} HISTCOUNT, {details.PO_ITEMS.Count} POITEMS");
            int cnt = 0;

            try
            {
                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 = ConvertSapDateToDateTime(det.ExpectedDeliveryDate);
                    if (det.QUANTITY <= det.QUANTITYPROCESSED) { posIsClosed = true; }

                    //GetMAKTXfromMATNR_IMPORT getMak = new GetMAKTXfromMATNR_IMPORT();
                    //getMak.MATNR = det.MATERIAL.Trim();
                    //GetMAKTXfromMATNR_EXPORT outMak = GetMAKTXfromMATNR(getMak);
                    //ItemText1 = outMak.MAKTX;

                    GrDataItem gr = new GrDataItem();
                    gr.AcceptedManufacturesLink = cnt.ToString();
                    gr.Created = ConvertSapDateToDateTime(details.PO_HEADER.CREATED_ON);
                    gr.LastUpdate = 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;
                    if (!det.SHORT_TEXT.Trim().Equals("")) { gr.ItemText1 = det.SHORT_TEXT; }
                    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); }
                    else { _log.Debug($"GetBest: Pos was not qualified for return => {gr}"); }
                }

                if (result.GrDataItems.Count == 0 && !useDetailsAlternative) 
                { 
                    _log.Debug($"No positions found, will now try alternative GET_DETAILS...");
                    result = GetBestellung(poNo, true);
                }
            }
            catch (Exception ex)
            {
                string ermsg = $"GetBestellung: General Error, please check LOG of ErpConnector!";
                _log.Error(ermsg + $" => {ex}");
                result.ErrorNumber = 900;
                result.MessageTechnical = result.MessageShort = ermsg;
            }

            // ==> MAYBE NEVER NEEDED: Lieferplan is also delivered with PO_DETAILS with sufficient rights
            //if (result.GrDataItems.Count == 0) //If no Items were found take a look at SAG instead of PO
            //{
            //    _log.Debug($"Could not find any PO Items, will now try and search for SAG '{poNo}'");
            //    try
            //    {
            //        BAPI_SAG_GETDETAIL_IMPORT sagInput = new BAPI_SAG_GETDETAIL_IMPORT();
            //        sagInput.PURCHASINGDOCUMENT = poNo;
            //        sagInput.SHIPPING_DATA = "X";
            //        sagInput.SCHEDULE_DATA = "X";
            //        sagInput.ITEM_DATA = "X";
            //        BAPI_SAG_GETDETAIL_EXPORT sagDetails = BAPI_SAG_GETDETAIL(sagInput);

            //        //TODO: Add logic if RFC works!
            //        //foreach ()
            //        //{

            //        //}
            //    }
            //    catch (Exception ex)
            //    {
            //        string ermsg = $"GetBestellung SAG: General Error, please check LOG of ErpConnector!";
            //        _log.Error(ermsg + $" => {ex}");
            //        result.ErrorNumber = 900;
            //        result.MessageTechnical = result.MessageShort = ermsg;
            //    }
            //}

            _log.Debug($"Result of GetBestellung now consists of {result.GrDataItems.Count} GrDataItems and {result.ManufacturerDataItems.Count} ManufacturerDataItems...");

            return result;
        }

        public static ApiResultMaterialdaten GetMaterialdaten(string itemNo)
        {
            ApiResultMaterialdaten result = new ApiResultMaterialdaten();
            string cumultMsg = "";

            BAPI_OBJCL_GETCLASSES_IMPORT input_getclasses = new BAPI_OBJCL_GETCLASSES_IMPORT();
            input_getclasses.CLASSTYPE_IMP = "Z02";
            input_getclasses.LANGUAGE = ConfigHelper.SapLanguage;
            input_getclasses.OBJECTKEY_IMP = itemNo.Trim().PadLeft(18, '0');
            input_getclasses.OBJECTTABLE_IMP = "MARA";
            BAPI_OBJCL_GETCLASSES_EXPORT output_getclasses = BAPI_OBJCL_GETCLASSES(input_getclasses);

            StringBuilder sb = new StringBuilder();
            foreach (BAPI1003_ALLOC_LIST alloc in output_getclasses.ALLOCLIST)
            {
                sb.Append($"CLASSNUM:{alloc.CLASSNUM} ");
                sb.Append($"OBJECT:{alloc.OBJECT} ");
                sb.Append($"OBJTYP:{alloc.OBJTYP} ");
                sb.Append($"STANDARDCLASS:{alloc.STANDARDCLASS} ");
                sb.Append($"STATUS:{alloc.STATUS} \n");
            }
            StringBuilder sb2 = new StringBuilder();
            foreach (BAPIRET2 ret in output_getclasses.RETURN)
            {
                sb2.Append($"TYPE:{ret.TYPE} ");
                sb2.Append($"ROW:{ret.ROW} ");
                sb2.Append($"PARAMETER:{ret.PARAMETER} ");
                sb2.Append($"MESSAGE:{ret.MESSAGE} ");
                sb2.Append($"ID:{ret.ID} ");
                sb2.Append($"FIELD:{ret.FIELD} ");
                sb2.Append($"MSGNO:{ret.LOG_MSG_NO} ");
                sb2.Append($"LOGNO:{ret.LOG_NO} ");
                sb2.Append($"MSG_V1:{ret.MESSAGE_V1} ");
                sb2.Append($"NUMBER:{ret.NUMBER} ");
                sb2.Append($"SYSTEM:{ret.SYSTEM} \n");

                if (ret.TYPE.Equals("I") || ret.TYPE.Equals("E"))
                {
                    cumultMsg += $"=> Fehlermeldung aus SAP ({ret.TYPE}|{ret.NUMBER}): " + ret.MESSAGE + " ||  ";
                }
            }
            _log.Debug($"Output GetClasses (Found {output_getclasses.ALLOCLIST.Count} items): \n {sb.ToString()} \n\nRETURN:\n{sb2.ToString()}");


            if (output_getclasses.RETURN.Count > 0 && output_getclasses.ALLOCLIST.Count > 0) //Only if results were received
            {
                if (output_getclasses.RETURN[0].TYPE.Equals("S")) //If successful 
                {
                    GetMATNRfromBMATN_EXPORT matnr_output = GetMATNRfromBMATN(new GetMATNRfromBMATN_IMPORT() { BMATN = itemNo });
                    _log.Debug($"Got MATNR for BAMTN: {matnr_output.MATNR}"); 
                    GetMAKTXfromMATNR_EXPORT maktx_output = GetMAKTXfromMATNR(new GetMAKTXfromMATNR_IMPORT() { MATNR = itemNo });
                    _log.Debug($"Got MAKTX for MATNR: {maktx_output.MAKTX}"); 

                    CLAF_CLASSIFICATION_OF_OBJECTS_IMPORT input_classification = new CLAF_CLASSIFICATION_OF_OBJECTS_IMPORT();
                    input_classification.CLASS = output_getclasses.ALLOCLIST[0].CLASSNUM; //Get Class Number of first entry
                    input_classification.CLASSTYPE = "Z02";
                    input_classification.OBJECT = itemNo.Trim().PadLeft(18, '0');
                    input_classification.LANGUAGE = ConfigHelper.SapLanguage;
                    input_classification.OBJECTTABLE = "MARA";
                    input_classification.INHERITED_CHAR = "X";
                    CLAF_CLASSIFICATION_OF_OBJECTS_EXPORT output_classification = CLAF_CLASSIFICATION_OF_OBJECTS(input_classification);

                    GetMsdMslEtcFromBMATN_IMPORT msdmsl_input = new GetMsdMslEtcFromBMATN_IMPORT();
                    msdmsl_input.BMATN = itemNo;
                    msdmsl_input.MATDESC = maktx_output.MAKTX;
                    msdmsl_input.T_OBJECTDATA = output_classification.T_OBJECTDATA;
                    GetMsdMslEtcFromBMATN_EXPORT output_msdmsl = GetMsdMslEtcFromBMATN(msdmsl_input);
                    result.MaterialDataItems = output_msdmsl.ITEMS;
                }
                else
                { return new ApiResultMaterialdaten() { ErrorNumber = 900, MessageShort = cumultMsg, MessageLong = cumultMsg, MessageTechnical = cumultMsg }; }
            }
            else
            {
                if (cumultMsg.Equals("")) { cumultMsg = "Keine Einträge im Materialstamm für diesen Artikel vorhanden"; }
                return new ApiResultMaterialdaten() { ErrorNumber = 901, MessageShort = cumultMsg, MessageLong = cumultMsg, MessageTechnical = cumultMsg };
            }

            return result;
        }

        public static ApiResultHerstellerdaten GetHerstellerdaten(string itemNo)
        {
            ApiResultHerstellerdaten result = new ApiResultHerstellerdaten();
            GET_MPN_DATA_IMPORT input = new GET_MPN_DATA_IMPORT() { BMATN = itemNo };
            GET_MPN_DATA_EXPORT sapRes = GET_MPN_DATA(input);

            _log.Debug($"GetHerstellerdaten in SAP-Connector was called, found {sapRes.MPN_DATA.Count} items when executing"); 

            foreach (GET_MPN_DATA_RESULTITEM temp in sapRes.MPN_DATA)
            {
                ManufacturerDataItem mf = new ManufacturerDataItem();
                mf.Created = temp.CREATED;
                mf.IsActive = true;
                mf.ItemNo = temp.BMATN.Trim();
                mf.LastUpdate = temp.CHANGED;
                mf.ManufacturerDescription = temp.NAME;
                mf.ManufacturerName = temp.NAME;
                mf.ManufacturerNo = mf.MPNCustom2 = temp.MFRNR;
                mf.ManufacturerValue = temp.MPN.Trim();
                mf.MPNCustom1 = temp.EMATN.Trim();
                result.ManufacturerDataItems.Add(mf);
                _log.Debug($"GetHerstellerdaten: Submitted entry => NAME: {mf.ManufacturerName}, NO: {mf.ManufacturerNo}, VAL: {mf.ManufacturerValue}"); 
            }

            return result;
        }

        //-----------------------------------------------------------------------------------------------------------------------------------------------------------------------

        public static ApiResultStringItems ExecuteGoodsMovement(GoodsMovementParameters par)
        {
            ApiResultStringItems result = new ApiResultStringItems();

            try
            {
                if (par == null) { throw new Exception($"GoodsMovementParameters are NULL!!!"); }
                _log.Debug($"ExecuteGoodsMovement => Received Item => {par.ToString()}");
                StringBuilder sb = new StringBuilder();
                sb.AppendLine($"\r\nSAP PARAMS GOODSMVT ===>");

                BAPI_GOODSMVT_CREATE_IMPORT import = new BAPI_GOODSMVT_CREATE_IMPORT();
                import.GOODSMVT_CODE.GM_CODE = par.MovementCode;

                //MAYBE DELETE LATER!
                par.UserName = ConfigHelper.SapDefaultUSER;

                BAPI2017_GM_HEAD_01 head = new BAPI2017_GM_HEAD_01();
                head.PR_UNAME = par.UserName; sb.AppendLine($"PR_UNAME: {par.UserName}");
                head.DOC_DATE = ConvertDateTimeToSapTime(DateTime.Now); sb.AppendLine($"DOC_DATE: {ConvertDateTimeToSapTime(DateTime.Now)}");
                head.REF_DOC_NO = par.RefDocNo; sb.AppendLine($"REF_DOC_NO: {par.RefDocNo}");
                head.PSTNG_DATE = par.PostingDate; sb.AppendLine($"PSTNG_DATE: {par.PostingDate}");
                import.GOODSMVT_HEADER = head; 

                foreach (GoodMovementItem moveit in par.MoveItems)
                {
                    sb.AppendLine($"\r\nMoveItem:");
                    BAPI2017_GM_ITEM_CREATE item = new BAPI2017_GM_ITEM_CREATE();
                    item.BATCH = moveit.Batch ?? ""; sb.AppendLine($"  BATCH: {item.BATCH ?? ""}");
                    item.EXPIRYDATE = moveit.ExpiryDate ?? ""; sb.AppendLine($"  EXPIRYDATE: {item.EXPIRYDATE ?? ""}");
                    item.MATERIAL = moveit.ItemNo ?? ""; sb.AppendLine($"  MATERIAL: {item.MATERIAL ?? ""}");
                    item.ITEM_TEXT = moveit.ItemText ?? ""; sb.AppendLine($"  ITEM_TEXT: {item.ITEM_TEXT}");
                    item.MVT_IND = moveit.MoveIndicator ?? ""; sb.AppendLine($"  MVT_IND: {item.MVT_IND}");
                    item.MOVE_TYPE = moveit.MoveType ?? ""; sb.AppendLine($"  MOVE_TYPE: {item.MOVE_TYPE}");
                    item.MOVE_BATCH = moveit.Move_Batch ?? ""; sb.AppendLine($"  MOVE_BATCH: {item.MOVE_BATCH}");
                    item.MOVE_PLANT = moveit.Move_Plant ?? ""; sb.AppendLine($"  MOVE_PLANT: {item.MOVE_PLANT}");
                    item.STGE_LOC = moveit.StorageLocation ?? ""; sb.AppendLine($"  STGE_LOC: {item.STGE_LOC}");
                    item.PO_NUMBER = moveit.OrderNo ?? ""; sb.AppendLine($"  PO_NUMBER: {item.PO_NUMBER}");
                    item.PO_ITEM = moveit.OrderPos ?? ""; sb.AppendLine($"  PO_ITEM: {item.PO_ITEM}");
                    item.PLANT = moveit.Plant ?? ""; sb.AppendLine($"  PLANT: {item.PLANT}");
                    item.ENTRY_QNT = Convert.ToInt32(moveit.Quantity); sb.AppendLine($"  ENTRY_QNT: {item.ENTRY_QNT}");
                    item.ENTRY_UOM = moveit.QuantityUnit ?? ""; sb.AppendLine($"  ENTRY_UOM: {item.ENTRY_UOM}");
                    item.SPEC_STOCK = moveit.SpecStock ?? ""; sb.AppendLine($"  SPEC_STOCK: {item.SPEC_STOCK ?? ""}");
                    item.STCK_TYPE = moveit.StockType ?? ""; sb.AppendLine($"  STCK_TYPE: {item.STCK_TYPE}");
                    item.VENDOR = moveit.Vendor ?? ""; sb.AppendLine($"  VENDOR: {item.VENDOR}");
                    import.GOODSMVT_ITEM.Add(item);
                }
                _log.Debug($"Added {import.GOODSMVT_ITEM.Count} items to GOODSMVT");
                _log.Debug(sb.ToString());
                BAPI_GOODSMVT_CREATE_EXPORT export = ZBAPI_GOODSMVT_CREATE(import);
                //BAPI_TRANSACTION_COMMIT();

                bool errorOccurred = false;
                string sapMessage = "";
                foreach (BAPIRET2 ret in export.RETURN) { if (ret.TYPE.Trim().Equals("E")) { errorOccurred = true; sapMessage += $"{ret.MESSAGE}  "; } }
                if (errorOccurred) 
                {
                    result.ErrorNumber = 900;
                    result.MessageTechnical = result.MessageLong = result.MessageShort = $"{sapMessage}";
                }
                else //In case of success return Materialbeleg as String 
                {
                    result.StringItems.Add(export.MATERIALDOCUMENT);
                }
            }
            catch (Exception ex)
            {
                string ermsg = $"Could not Execute GoodMovement! => {ex}";
                _log.Error(ermsg);
                result.ErrorNumber = 900;
                result.MessageShort = ermsg;
            }

            return result;
        }

        //-----------------------------------------------------------------------------------------------------------------------------------------------------------------------

        private static DateTime ConvertSapDateToDateTime(string sapDate, bool delimitersUsed = true)
        {
            if ((sapDate ?? "").Equals("")) { sapDate = "2199-01-01"; }
            _log.Debug($"SapDateConversion => Input = '{sapDate}' ");

            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);
            }
        }
        private static string ConvertDateTimeToSapTime(DateTime date)
        {
            if (date == null) { return "00000000"; }
            return date.ToString("yyyyMMdd");
        }
        private 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 GetMsdMslEtcFromBMATN_EXPORT GetMsdMslEtcFromBMATN(GetMsdMslEtcFromBMATN_IMPORT import)
        {
            string errorMsg = "";
            GetMsdMslEtcFromBMATN_EXPORT export = new GetMsdMslEtcFromBMATN_EXPORT();

            try
            {
                RfcDestination dest = RfcDestinationManager.GetDestination(ConfigHelper.ActiveSapDestinationName);
                IRfcFunction funcMara4 = dest.Repository.CreateFunction("RFC_READ_TABLE"); //Create Function
                IRfcTable t4 = funcMara4.GetTable("DATA");
                t4.Clear();
                IRfcTable options = funcMara4.GetTable("OPTIONS");
                options.Clear();
                options.Append();
                options.SetValue("TEXT", "BMATN = '" + import.BMATN?.Trim().PadLeft(18, '0') + "'");
                options.Append();
                IRfcTable fields4 = funcMara4.GetTable("FIELDS");
                fields4.Append(3);
                fields4.CurrentIndex = 0; fields4.SetValue(0, "MHDHB");
                fields4.CurrentIndex = 1; fields4.SetValue(0, "ERSDA");
                fields4.CurrentIndex = 2; fields4.SetValue(0, "LAEDA");
                funcMara4.SetValue("QUERY_TABLE", "MARA"); //Set Value to function
                funcMara4.SetValue("DELIMITER", ";"); //Set Value to function
                funcMara4.SetValue("USE_ET_DATA_4_RETURN", "0");
                funcMara4.Invoke(dest); //Invoke function at Sap destination

                IRfcTable rfcTable4 = funcMara4.GetTable("DATA"); //Process return values
                int rowCount4 = rfcTable4.Count;
                foreach (IRfcStructure structure in rfcTable4)
                {
                    string[] line = structure.GetString(0).Split(';'); //Was GetString(i) before => i = rowCount4;
                    CLOBJDAT mslRow = new CLOBJDAT();
                    foreach (CLOBJDAT cl in import.T_OBJECTDATA)
                    {
                        if (cl.SMBEZ.Equals("moisture sensitiv level") || cl.SMBEZ.Equals("Feuchteklasse")) { mslRow = cl; }
                    }
                    string mslLvl = "1";
                    if (mslRow.AUSP1 != null) { if (!mslRow.AUSP1.Equals("?")) { mslLvl = mslRow.AUSP1; } }//Get MSL

                    DateTime created;  //Calculate Dates
                    DateTime lastUpdate;
                    if (!line[1].Equals("00000000") && !line[1].Equals("") && line[1].Length >= 8)
                    {
                        created = new DateTime(
                            Convert.ToInt32(line[1].Substring(0, 4)),
                            Convert.ToInt32(line[1].Substring(4, 2)),
                            Convert.ToInt32(line[1].Substring(6, 2)));
                    }
                    else { created = DateTime.Now; }
                    if (!line[2].Equals("00000000") && !line[2].Equals("") && line[2].Length >= 8)
                    {
                        lastUpdate = new DateTime(
                             Convert.ToInt32(line[2].Substring(0, 4)),
                             Convert.ToInt32(line[2].Substring(4, 2)),
                             Convert.ToInt32(line[2].Substring(6, 2)));
                    }
                    else { lastUpdate = DateTime.Now; }

                    int? timeSpan = Convert.ToInt32(line[0]);
                    if (timeSpan == 0) { timeSpan = null; }

                    export.ITEMS.Add(new ItemsItem() //Build up new ItemsItem for returning
                    {
                        Created = created,
                        LastUpdate = lastUpdate,
                        ItemNo = import.BMATN,
                        ItemText1 = import.MATDESC,
                        MSL = mslLvl,
                        UsableTimeSpanValue = timeSpan,
                        CustomValue01 = "",
                        IsRoHS = false,
                        ContainerType = "" //TODO: Take ID from DB
                    });
                }
            }
            catch (Exception ex) { errorMsg += "CI: SAP Other Exception: " + ex; }

            if (!errorMsg.Equals("")) { _log.Error(errorMsg); }

            return export;
        }

        //-----------------------------------------------------------------------------------------------------------------------------------------------------------------------

        private 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;
        }
        private 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;
        }

        private 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();
            export.PO_ITEMS = new List<BAPIEKPO>();
            List<BAPIEKPO> poItemBuffer = new List<BAPIEKPO>();


            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");

                    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") ?? "";
                        temp.PO_ITEM = row.GetString("PO_ITEM") ?? "";
                        temp.STATUS = row.GetString("STATUS") ?? "";
                        temp.CHANGED_ON = row.GetString("CHANGED_ON") ?? "";
                        temp.SHORT_TEXT = row.GetString("SHORT_TEXT") ?? "";
                        temp.MATERIAL = row.GetString("MATERIAL") ?? "";
                        temp.PUR_MAT = row.GetString("PUR_MAT") ?? "";
                        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);
                        export.PO_ITEMS.Add(temp);

                        _log.Debug($"Received PO_ITEM => NO={temp.PO_NUMBER}, Item={temp.PO_ITEM}, DELETE_IND => {temp.DELETE_IND} Quan={temp.QUANTITY}");
                    }

                    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_TOTALS.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);
                    }

                    _log.Debug($"BAPI_PO_GETDETAILS: Received {poItemBuffer.Count} PO_ITEMS, {export.PO_ITEM_HISTORY_TOTALS.Count} PO_ITEM_HISTORY_TOTALS, {export.PO_ITEM_HISTORY.Count} PO_ITEM_HISTORY");
                }
                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;
        }
        private static BAPI_PO_GETDETAIL_EXPORT BAPI_PO_GETDETAILS1(BAPI_PO_GETDETAIL_IMPORT import)
        {
            string errorMsg = "";
            BAPI_PO_GETDETAIL_EXPORT export = new BAPI_PO_GETDETAIL_EXPORT();
            export.PO_ITEMS = new List<BAPIEKPO>();
            List<BAPIEKPO> poItemBuffer = new List<BAPIEKPO>();

            if (import != null)
            {
                try
                {
                    RfcDestination dest = RfcDestinationManager.GetDestination(ConfigHelper.ActiveSapDestinationName);
                    IRfcFunction func = dest.Repository.CreateFunction("BAPI_PO_GETDETAIL1"); //Create Function with BAPI_PO_GETDETAIL1
                    func.SetValue("PURCHASEORDER", import.PURCHASEORDER?.Trim().PadLeft(10, '0')); //Set Value to function

                    // Set optional parameters for BAPI_PO_GETDETAIL1
                    func.SetValue("ACCOUNT_ASSIGNMENT", "X");
                    func.SetValue("ITEM_TEXT", "X");
                    func.SetValue("HEADER_TEXT", "X");
                    func.SetValue("DELIVERY_ADDRESS", "X");
                    func.SetValue("VERSION", "X");
                    func.SetValue("SERVICES", "X");
                    func.SetValue("SERIALNUMBERS", "X");
                    func.SetValue("INVOICEPLAN", "X");

                    func.Invoke(dest); //Invoke function at Sap destination

                    // Export: POHEADER
                    IRfcStructure po_header_struct = func.GetStructure("POHEADER");
                    export.PO_HEADER.PO_NUMBER = po_header_struct.GetString("PO_NUMBER");
                    export.PO_HEADER.CREATED_ON = po_header_struct.GetString("DOC_DATE") ?? "";
                    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("VENDOR_NAME") ?? "";

                    // Tables: POITEM
                    IRfcTable po_items_table = func.GetTable("POITEM");
                    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("PO_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("PURCHASING_MAT_NO")?.TrimStart('0') ?? "";
                        temp.QUANTITY = row.GetDecimal("QUANTITY");
                        temp.UNIT = row.GetString("UNIT") ?? "";
                        temp.PLANT = row.GetString("PLANT") ?? "";
                        temp.MAT_GRP = row.GetString("MATL_GROUP") ?? "";
                        temp.ACCTASSCAT = row.GetString("ACCTASSCAT") ?? "";
                        temp.QUAL_INSP = row.GetString("QUAL_INSP") ?? "";
                        temp.MANU_MAT = row.GetString("MANU_MAT") ?? "";
                        temp.MFR_NO = row.GetString("MANUF_NO") ?? "";
                        temp.VEND_MAT = row.GetString("VENDOR_MATERIAL_NO") ?? "";
                        temp.STOR_LOC = row.GetString("STORAGE_LOCATION") ?? "";
                        temp.DELETE_IND = row.GetString("DELETE_IND") ?? "";
                        poItemBuffer.Add(temp);
                        export.PO_ITEMS.Add(temp);

                        _log.Debug($"Received PO_ITEM => NO={temp.PO_NUMBER}, Item={temp.PO_ITEM}, DELETE_IND => {temp.DELETE_IND} Quan={temp.QUANTITY}");
                    }

                    // Tables: POHISTORY_TOTALS
                    IRfcTable po_item_hist_total = func.GetTable("POHISTORY_TOTALS");
                    foreach (IRfcStructure row in po_item_hist_total)
                    {
                        BAPIEKBES temp = new BAPIEKBES();
                        temp.BLOCKED_QY = row.GetDecimal("BLOCKED_QTY");
                        temp.BL_QTY = row.GetDecimal("BL_QTY");
                        temp.BL_QTY_TOTAL = row.GetDecimal("BL_QTY_TOTAL");
                        temp.DELIV_QTY = row.GetDecimal("DELIVERY_QTY");
                        temp.DL_QTY_TOTAL = row.GetDecimal("DL_QTY_TOTAL");
                        temp.DL_QTY_TRSP = row.GetDecimal("DL_QTY_TRSP");
                        temp.IV_QTY = row.GetDecimal("INVOICE_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("ORDER_QTY");
                        temp.SERIAL_NO = row.GetString("SERIAL_NO")?.TrimStart('0') ?? "";
                        temp.WITHDR_QTY = row.GetDecimal("WITHDRAWAL_QTY");
                        export.PO_ITEM_HISTORY_TOTALS.Add(temp);
                    }

                    // Tables: POHISTORY
                    IRfcTable po_item_hist = func.GetTable("POHISTORY");
                    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("MATDOC_NO") ?? "";
                        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("POSTING_DATE") ?? "";
                        temp.PUR_MAT = row.GetString("PURCHASING_MATERIAL") ?? "";
                        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("DELIVERY_QTY");
                        temp.DELIV_UNIT = row.GetString("DELIVERY_UNIT") ?? "";
                        export.PO_ITEM_HISTORY.Add(temp);
                    }

                    _log.Debug($"BAPI_PO_GETDETAIL1: Received {poItemBuffer.Count} POITEM, {export.PO_ITEM_HISTORY_TOTALS.Count} POHISTORY_TOTALS, {export.PO_ITEM_HISTORY.Count} POHISTORY");
                }
                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;
        }
        private static BAPI_SAG_GETDETAIL_EXPORT BAPI_SAG_GETDETAIL(BAPI_SAG_GETDETAIL_IMPORT import)
        {
            string errorMsg = "";
            BAPI_SAG_GETDETAIL_EXPORT export = new BAPI_SAG_GETDETAIL_EXPORT();

            if (import != null)
            {
                try
                {
                    RfcDestination dest = RfcDestinationManager.GetDestination(ConfigHelper.ActiveSapDestinationName);
                    IRfcFunction func = dest.Repository.CreateFunction("BAPI_SAG_GETDETAIL"); //Create Function with BAPI_PO_GETDETAIL1
                    func.SetValue("PURCHASINGDOCUMENT", import.PURCHASINGDOCUMENT?.Trim().PadLeft(10, '0')); //Set Value to function

                    // Set optional parameters 
                    func.SetValue("SHIPPING_DATA", import.SHIPPING_DATA);
                    func.SetValue("ITEM_DATA", import.ITEM_DATA);
                    func.SetValue("SCHEDULE_DATA", import.SCHEDULE_DATA);
                    func.Invoke(dest); //Invoke function at Sap destination

                    IRfcStructure structHead = func.GetStructure("HEADER");
                    export.HEADER = new BAPIMEOUTHEADER();
                    export.HEADER.COMP_CODE = structHead.GetString("COMP_CODE");
                    export.HEADER.DOC_TYPE = structHead.GetString("DOC_TYPE");
                    export.HEADER.NUMBER = structHead.GetString("NUMBER");
                    export.HEADER.STATUS = structHead.GetString("STATUS");
                    export.HEADER.VENDOR = structHead.GetString("VENDOR");
                    _log.Debug($"SAG HEAD => COMP_CODE={export.HEADER.COMP_CODE}, DOC_TYPE={export.HEADER.DOC_TYPE}, NUMBER={export.HEADER.NUMBER}, STATUS={export.HEADER.STATUS}, VENDOR={export.HEADER.VENDOR}");

                    // RETURN-Tabelle prüfen
                    IRfcTable returnTable = func.GetTable("RETURN");
                    foreach (IRfcStructure row in returnTable)
                    {
                        _log.Error($"RETURN => Type={row.GetString("TYPE")}, ID={row.GetString("ID")}, Number={row.GetString("NUMBER")}, Message={row.GetString("MESSAGE")}");
                    }

                    // Tables: SCHEDULE
                    IRfcTable schedule_table = func.GetTable("SCHEDULE");
                    _log.Debug($"Schedule Rows: {schedule_table.RowCount}");
                    foreach (IRfcStructure row in schedule_table)
                    {
                        BAPIMEOUTSCHEDULE sched = new BAPIMEOUTSCHEDULE();
                        sched.DELETE_IND = row.GetString("DELETE_IND");
                        sched.DELIVERY_DATE = row.GetString("DELIVERY_DATE");
                        sched.ITEM_NO = row.GetString("ITEM_NO");
                        sched.QUANTITY = row.GetDecimal("QUANTITY");
                        sched.REQ_CLOSED = row.GetString("REQ_CLOSED");
                        sched.SCHED_LINE = row.GetString("SCHED_LINE");
                        export.SCHEDULE.Add(sched);
                    }

                    // Tables: SHIPPING
                    IRfcTable shipping_table = func.GetTable("SHIPPING");
                    _log.Debug($"Shipping Rows: {shipping_table.RowCount}");
                    foreach (IRfcStructure row in shipping_table)
                    {
                        BAPIMEPOSHIPPEXP ship = new BAPIMEPOSHIPPEXP();
                        ship.DEL_CREATE_TIME = row.GetDecimal("DEL_CREATE_TIME").ToString();
                        ship.DLV_PRIO = row.GetString("DLV_PRIO");
                        ship.PLND_DELRY = row.GetDecimal("PLND_DELRY");
                        ship.PO_ITEM = row.GetString("PO_ITEM");
                        ship.SRC_DLV_NO = row.GetString("SRC_DLV_NO");
                        export.SHIPPING.Add(ship);
                    }

                    // Tables: ITEM
                    IRfcTable item_table = func.GetTable("ITEM");
                    _log.Debug($"Item Rows: {item_table.RowCount}");
                    foreach (IRfcStructure row in item_table)
                    {
                        //BAPIMEPOSHIPPEXP ship = new BAPIMEPOSHIPPEXP();
                        //ship.DEL_CREATE_TIME = row.GetDecimal("DEL_CREATE_TIME").ToString();
                        //ship.DLV_PRIO = row.GetString("DLV_PRIO");
                        //ship.PLND_DELRY = row.GetDecimal("PLND_DELRY");
                        //ship.PO_ITEM = row.GetString("PO_ITEM");
                        //ship.SRC_DLV_NO = row.GetString("SRC_DLV_NO");
                        //export.ITEM.Add(ship);
                    }

                    _log.Debug($"BAPI_SAG_GETDETAIL: Received {export.SHIPPING.Count} SHIPPING items and {export.SCHEDULE.Count} SCHEDULE items");
                }
                catch (Exception ex) { errorMsg += "CI: SAP Other Exception: " + ex; }
            }
            else { _log.Debug("Error, IMPORT for BAPI_SAG_GETDETAIL was NULL! "); }

            if (!errorMsg.Equals("")) { _log.Debug(errorMsg); }

            return export;
        }

        private static BAPI_OBJCL_GETCLASSES_EXPORT BAPI_OBJCL_GETCLASSES(BAPI_OBJCL_GETCLASSES_IMPORT import)
        {
            string errorMsg = "";
            BAPI_OBJCL_GETCLASSES_EXPORT export = new BAPI_OBJCL_GETCLASSES_EXPORT();

            try
            {
                RfcDestination dest = RfcDestinationManager.GetDestination(ConfigHelper.ActiveSapDestinationName);
                IRfcFunction func = dest.Repository.CreateFunction("BAPI_OBJCL_GETCLASSES");
                func.SetValue("OBJECTKEY_IMP", import.OBJECTKEY_IMP);
                func.SetValue("OBJECTTABLE_IMP", import.OBJECTTABLE_IMP);
                func.SetValue("CLASSTYPE_IMP", import.CLASSTYPE_IMP);
                func.SetValue("READ_VALUATIONS", import.READ_VALUATIONS);
                func.SetValue("LANGUAGE", import.LANGUAGE);
                func.Invoke(dest);

                IRfcTable allocList_table = func.GetTable("ALLOCLIST");
                foreach (IRfcStructure row in allocList_table)
                {
                    export.ALLOCLIST.Add(new BAPI1003_ALLOC_LIST()
                    {
                        CLASSNUM = row.GetString("CLASSNUM"),
                        CLASSTYPE = row.GetString("CLASSTYPE"),
                        STANDARDCLASS = row.GetString("STANDARDCLASS"),
                        STATUS = row.GetString("STATUS"),
                        OBJECT = row.GetString("OBJECT"),
                        OBJTYP = row.GetString("OBJTYP")
                    });
                }

                IRfcTable return_table = func.GetTable("RETURN");
                foreach (IRfcStructure row in return_table)
                {
                    export.RETURN.Add(new BAPIRET2()
                    {
                        NUMBER = row.GetString("NUMBER"),
                        ID = row.GetString("ID"),
                        FIELD = row.GetString("FIELD"),
                        LOG_MSG_NO = row.GetString("LOG_MSG_NO"),
                        LOG_NO = row.GetString("LOG_NO"),
                        MESSAGE = row.GetString("MESSAGE"),
                        MESSAGE_V1 = row.GetString("MESSAGE_V1"),
                        MESSAGE_V2 = row.GetString("MESSAGE_V2"),
                        MESSAGE_V3 = row.GetString("MESSAGE_V3"),
                        MESSAGE_V4 = row.GetString("MESSAGE_V4"),
                        PARAMETER = row.GetString("PARAMETER"),
                        TYPE = row.GetString("TYPE"),
                        SYSTEM = row.GetString("SYSTEM"),
                        ROW = row.GetString("ROW")
                    });
                }
            }
            catch (Exception ex) { errorMsg += "CI: SAP Other Exception: " + ex; }

            if (!errorMsg.Equals("")) { _log.Error(errorMsg); }

            return export;
        }
        private static BAPI_OBJCL_CHANGE_EXPORT BAPI_OBJCL_CHANGE(BAPI_OBJCL_CHANGE_IMPORT import)
        {
            string errorMsg = "";
            BAPI_OBJCL_CHANGE_EXPORT export = new BAPI_OBJCL_CHANGE_EXPORT();

            try
            {
                RfcDestination dest = RfcDestinationManager.GetDestination(ConfigHelper.ActiveSapDestinationName);
                IRfcFunction func = dest.Repository.CreateFunction("BAPI_BATCH_SAVE_REPLICA"); //BAPI_BATCH_SAVE_REPLICA
                func.SetValue("BATCH", import.BATCH.Trim().PadLeft(10, '0'));
                func.SetValue("MATERIAL", import.MATERIAL?.Trim().PadLeft(18, '0'));
                func.SetValue("PLANT", import.PLANT.Trim().PadLeft(4, '0'));
                func.SetValue("BATCHSTORAGELOCATION", import.BATCHSTORAGELOCATION.Trim().PadLeft(4, '0'));
                IRfcTable classallocations = func.GetTable("CLASSALLOCATIONS");
                foreach (BAPI3060_ALLOCATION alloc in import.CLASSALLOCATIONS)
                {
                    classallocations.Append();
                    classallocations.SetValue("CLASSNUM", "CHARGE_ELEKTR"); //could also be alloc.CLASSNUM
                    classallocations.SetValue("CLASS_TYPE", alloc.CLASS_TYPE);
                    classallocations.SetValue("OBJECTKEY", alloc.OBJECTKEY);
                    classallocations.SetValue("OBJECTTABLE", alloc.OBJECTTABLE);
                }
                IRfcTable valchars = func.GetTable("CLASSVALUATIONSCHAR");
                foreach (BAPI3060_VALUATION_CHAR val in import.CLASSVALUATIONSCHAR)
                {
                    valchars.Append();
                    valchars.SetValue("CHARACT", val.CHARACT);
                    valchars.SetValue("VALUE_CHAR", val.VALUE_FROM);
                }
                IRfcTable valnums = func.GetTable("CLASSVALUATIONSNUM");
                foreach (BAPI3060_VALUATION_NUM val in import.CLASSVALUATIONSNUM)
                {
                    valnums.Append();
                    valnums.SetValue("CHARACT", val.CHARACT);
                    valnums.SetValue("VALUE_FROM", val.VALUE_FROM);
                }

                IRfcStructure extension1 = func.GetStructure("EXTENSION1");
                extension1.SetValue("ZZMFRNR", import.EXTENSION1.ZZMFRNR);
                extension1.SetValue("ZZMFRPN", import.EXTENSION1.ZZMFRPN);
                extension1.SetValue("ZZEMATN", import.EXTENSION1.ZZEMATN);

                func.Invoke(dest);

                IRfcTable ret_table = func.GetTable("RETURN");
                _log.Debug($"BAPI_OBCL_CHANGE found {ret_table.Count} rows in RETURN"); 
                foreach (IRfcStructure row in ret_table)
                {
                    BAPIRET2 temp = new BAPIRET2();
                    temp.FIELD = ret_table.GetString("FIELD");
                    temp.ID = ret_table.GetString("ID");
                    temp.LOG_MSG_NO = ret_table.GetString("LOG_MSG_NO");
                    temp.LOG_NO = ret_table.GetString("LOG_NO");
                    temp.MESSAGE = ret_table.GetString("MESSAGE");
                    temp.MESSAGE_V1 = ret_table.GetString("MESSAGE_V1");
                    temp.MESSAGE_V2 = ret_table.GetString("MESSAGE_V2");
                    temp.MESSAGE_V3 = ret_table.GetString("MESSAGE_V3");
                    temp.MESSAGE_V4 = ret_table.GetString("MESSAGE_V4");
                    temp.NUMBER = ret_table.GetString("NUMBER");
                    temp.PARAMETER = ret_table.GetString("PARAMETER");
                    temp.ROW = ret_table.GetString("ROW");
                    temp.SYSTEM = ret_table.GetString("SYSTEM");
                    temp.TYPE = ret_table.GetString("TYPE");
                    export.RETURN.Add(temp);

                    _log.Debug($"Return ({temp.TYPE} | {temp.ID} | NUM:{temp.NUMBER}): " + temp.MESSAGE + $" | V1:{temp.MESSAGE_V1} | V2:{temp.MESSAGE_V2} | V3:{temp.MESSAGE_V3} | V4:{temp.MESSAGE_V4}"); 
                }
            }
            catch (Exception ex) { errorMsg += "CI: SAP Other Exception: " + ex; }

            if (!errorMsg.Equals("")) { _log.Debug(errorMsg); }

            return export;
        }

        private static GET_MPN_DATA_EXPORT GET_MPN_DATA(GET_MPN_DATA_IMPORT import)
        {
            string errorMsg = "";
            GET_MPN_DATA_EXPORT export = new GET_MPN_DATA_EXPORT();
            List<GET_MPN_DATA_TEMPITEM> step1and2data = new List<GET_MPN_DATA_TEMPITEM>();

            try //STEP 1 ------------------------------------------------------
            {
                RfcDestination dest = RfcDestinationManager.GetDestination(ConfigHelper.ActiveSapDestinationName);
                IRfcFunction func = dest.Repository.CreateFunction("RFC_READ_TABLE");
                IRfcTable t = func.GetTable("DATA"); t.Clear(); //Get once so it could be appended in result
                IRfcTable options = func.GetTable("OPTIONS");
                options.Clear();
                options.Append();
                options.SetValue("TEXT", "BMATN = '" + import.BMATN?.Trim().PadLeft(18, '0') + "'"); //Set Query-text
                options.Append();
                IRfcTable fields = func.GetTable("FIELDS");
                fields.Append(4);
                fields.CurrentIndex = 0; fields.SetValue(0, "BMATN"); //BMATN
                fields.CurrentIndex = 1; fields.SetValue(0, "EMATN"); //EMATN
                fields.CurrentIndex = 2; fields.SetValue(0, "MFRNR"); //MFRNR
                fields.CurrentIndex = 3; fields.SetValue(0, "AMPSP"); //AMPSP
                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);

                IRfcTable rfcTable = func.GetTable("DATA"); //Process return values
                _log.Debug($"GET_MPN_DATA_STEP1: Found {rfcTable.Count} entries"); 
                foreach (IRfcStructure structure in rfcTable)
                {
                    string[] line = structure.GetString(0).Split(';');
                    if (line[3].Equals("0004") || line[3].Trim().Equals("") || line[3].Equals("blank"))
                    {
                        GET_MPN_DATA_TEMPITEM temp = new GET_MPN_DATA_TEMPITEM();
                        temp.BMATN = line[0];
                        temp.EMATN = line[1];
                        temp.MFRNR = line[2];
                        temp.AMPSP = line[3];
                        temp.NAME = "";
                        step1and2data.Add(temp); //Add new entry if not locked
                        _log.Debug("GET_MPN_DATA => READTABLE: Added entry " + structure.GetString(0)); 
                    }
                }
            }
            catch (Exception ex) { errorMsg += "CI: SAP Other Exception: " + ex; }

            if (!errorMsg.Equals("")) { errorMsg += "\n\n"; }

            try //STEP 2 ------------------------------------------------------
            {
                foreach (GET_MPN_DATA_TEMPITEM s1 in step1and2data)
                {
                    RfcDestination dest = RfcDestinationManager.GetDestination(ConfigHelper.ActiveSapDestinationName);
                    IRfcFunction func = dest.Repository.CreateFunction("BAPI_VENDOR_GETDETAIL"); //Create Function

                    func.SetValue("VENDORNO", s1.MFRNR?.TrimStart('0').PadLeft(10, '0')); //Build RFC_DB_OPT
                    func.SetValue("COMPANYCODE", ""); //Leave blank => not needed for queriing table
                    func.Invoke(dest); //Invoke function at Sap destination

                    IRfcStructure rfcStruct = func.GetStructure("GENERALDETAIL"); //Process return values, only 1 should come
                    s1.NAME = rfcStruct.GetString("NAME"); //Set Name to it
                    _log.Debug($"Found Name |{s1.NAME}| for MfrNo {s1.MFRNR}"); 
                }
            }
            catch (Exception ex) { errorMsg += "CI: SAP Other Exception: " + ex; }

            if (!errorMsg.Equals("")) { errorMsg += "\n\n"; }

            try //STEP 3 ------------------------------------------------------
            {
                foreach (GET_MPN_DATA_TEMPITEM s2 in step1and2data)
                {
                    //Destination Configuration
                    RfcDestination dest = RfcDestinationManager.GetDestination(ConfigHelper.ActiveSapDestinationName); //SAP Detsination Name
                    IRfcFunction func = dest.Repository.CreateFunction("RFC_READ_TABLE"); //Create Function
                    IRfcTable t = func.GetTable("DATA");
                    t.Clear();
                    IRfcTable options = func.GetTable("OPTIONS");
                    options.Clear();
                    options.Append();
                    options.SetValue("TEXT", "MATNR = '" + s2.EMATN.Trim().PadLeft(18, '0') + "' ");
                    options.Append();
                    options.SetValue("TEXT", "AND MFRNR = '" + s2.MFRNR?.Trim().PadLeft(6, '0') + "' ");
                    options.Append();
                    IRfcTable fields = func.GetTable("FIELDS");
                    fields.Append(3);
                    fields.CurrentIndex = 0; fields.SetValue(0, "MFRPN");
                    fields.CurrentIndex = 1; fields.SetValue(0, "ERSDA");
                    fields.CurrentIndex = 2; fields.SetValue(0, "LAEDA");
                    func.SetValue("QUERY_TABLE", "MARA"); //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 rfcTable = func.GetTable("DATA"); //Process return values
                    int rowCount = rfcTable.Count;
                    _log.Debug($"GET_MPN_DATA_STEP3: Found {rfcTable.Count} entries"); 
                    foreach (IRfcStructure structure in rfcTable)
                    {
                        string[] line = structure.GetString(0).Split(';');
                        DateTime created = DateTime.Now;
                        DateTime lastUpdate = DateTime.Now;

                        if (!line[1].Equals("00000000") && !line[1].Equals("")) //Calculate Dates
                        {
                            try { created = new DateTime(Convert.ToInt32(line[1].Substring(0, 4)), Convert.ToInt32(line[1].Substring(4, 2)), Convert.ToInt32(line[1].Substring(6, 2))); } catch (Exception e) { _log.Error($"line[1] date not convertible! => {line[1] ?? ""}\r\n {e}"); }
                        }
                        else { created = DateTime.Now; }
                        if (!line[2].Equals("00000000") && !line[2].Equals(""))
                        {
                            try { lastUpdate = new DateTime(Convert.ToInt32(line[2].Substring(0, 4)), Convert.ToInt32(line[2].Substring(4, 2)), Convert.ToInt32(line[2].Substring(6, 2))); } catch (Exception e) { _log.Error($"line[2] date not convertible! => {line[2] ?? ""}\r\n {e}"); }
                        }
                        else { lastUpdate = DateTime.Now; }

                        GET_MPN_DATA_RESULTITEM res = new GET_MPN_DATA_RESULTITEM(); //Add Result
                        res.CREATED = created;
                        res.CHANGED = lastUpdate;
                        res.BMATN = s2.BMATN.TrimStart('0');
                        res.EMATN = s2.EMATN.TrimStart('0');
                        res.MFRNR = s2.MFRNR.TrimStart('0');
                        res.NAME = s2.NAME.TrimStart('0');
                        res.AMPSP = s2.AMPSP;
                        res.MPN = line[0];
                        export.MPN_DATA.Add(res);

                        _log.Debug($"GET_MPN_DATA => READTABLE Step 3: Added entry {s2.NAME.TrimStart('0')}, {s2.MFRNR.TrimStart('0')}"); 
                    }
                }
            }
            catch (Exception ex) { errorMsg += "CI: SAP Other Exception: " + ex; }

            if (!errorMsg.Equals("")) { _log.Error(errorMsg); }

            return export;
        }

        //private static BAPI_MATERIAL_GETALL_EXPORT BAPI_MATERIAL_GETALL(BAPI_MATERIAL_GETALL_IMPORT import)
        //{
        //    string errorMsg = "";
        //    BAPI_MATERIAL_GETALL_EXPORT export = new BAPI_MATERIAL_GETALL_EXPORT();

        //    try
        //    {
        //        RfcDestination dest = RfcDestinationManager.GetDestination(ConfigHelper.ActiveSapDestinationName);
        //        IRfcFunction func = dest.Repository.CreateFunction("BAPI_MATERIAL_GETALL"); //Create Function
        //        func.SetValue("MATERIAL", import.MATERIAL?.Trim().PadLeft(18, '0')); //Set Value to function
        //        if (!import.WAREHOUSENUMBER.Equals(string.Empty)) { func.SetValue("WAREHOUSENUMBER", import.WAREHOUSENUMBER?.Trim().PadLeft(3, '0')); } //Set Value to function
        //        func.Invoke(dest); //Invoke function at Sap destination

        //        IRfcStructure clientdata_struct = func.GetStructure("CLIENTDATA");
        //        export.CLIENTDATA.MATERIAL = clientdata_struct.GetString("MATERIAL");
        //        export.CLIENTDATA.MATL_TYPE = clientdata_struct.GetString("MATL_TYPE");
        //        export.CLIENTDATA.CREATED_ON = clientdata_struct.GetString("CREATED_ON");
        //        export.CLIENTDATA.LAST_CHNGE = clientdata_struct.GetString("LAST_CHNGE");
        //        export.CLIENTDATA.CREATED_BY = clientdata_struct.GetString("CREATED_BY");
        //        export.CLIENTDATA.CHANGED_BY = clientdata_struct.GetString("CHANGED_BY");
        //        export.CLIENTDATA.MATL_GROUP = clientdata_struct.GetString("MATL_GROUP");
        //        export.CLIENTDATA.BASE_UOM = clientdata_struct.GetString("BASE_UOM");
        //        export.CLIENTDATA.BASE_UOM_ISO = clientdata_struct.GetString("BASE_UOM_ISO");
        //        export.CLIENTDATA.SHELF_LIFE = clientdata_struct.GetString("SHELF_LIFE");
        //        export.CLIENTDATA.PUR_STATUS = clientdata_struct.GetString("PUR_STATUS");
        //        export.CLIENTDATA.MANU_MAT = clientdata_struct.GetString("MANU_MAT");
        //        export.CLIENTDATA.MFR_NO = clientdata_struct.GetString("MFR_NO");
        //        _log.Debug($"CLIENTDATA: MATERIAL={export.CLIENTDATA.MATERIAL} | MFR:{export.CLIENTDATA.MFR_NO}"); 

        //        IRfcStructure plantdata_struct = func.GetStructure("PLANTDATA");
        //        export.PLANTDATA.PLANT = plantdata_struct.GetString("PLANT");

        //        IRfcStructure storedata_struct = func.GetStructure("STORAGELOCATIONDATA");
        //        export.STORAGELOCATIONDATA.STGE_LOC = storedata_struct.GetString("STGE_LOC");
        //        export.STORAGELOCATIONDATA.PLANT = storedata_struct.GetString("PLANT");

        //        IRfcStructure warehouse_struct = func.GetStructure("WAREHOUSENUMBERDATA");
        //        export.WAREHOUSENUMBERDATA.WHSE_NO = warehouse_struct.GetString("WHSE_NO");
        //        export.WAREHOUSENUMBERDATA.LEQ_UNIT_1 = warehouse_struct.GetString("LEQ_UNIT_1");
        //        export.WAREHOUSENUMBERDATA.LEQ_UNIT_1_ISO = warehouse_struct.GetString("LEQ_UNIT_1_ISO");
        //        export.WAREHOUSENUMBERDATA.LEQ_UNIT_2 = warehouse_struct.GetString("LEQ_UNIT_2");
        //        export.WAREHOUSENUMBERDATA.LEQ_UNIT_2_ISO = warehouse_struct.GetString("LEQ_UNIT_2_ISO");
        //        export.WAREHOUSENUMBERDATA.LEQ_UNIT_3 = warehouse_struct.GetString("LEQ_UNIT_3");
        //        export.WAREHOUSENUMBERDATA.LEQ_UNIT_3_ISO = warehouse_struct.GetString("LEQ_UNIT_3_ISO");
        //        export.WAREHOUSENUMBERDATA.L_EQUIP_1 = warehouse_struct.GetString("L_EQUIP_1");
        //        export.WAREHOUSENUMBERDATA.L_EQUIP_2 = warehouse_struct.GetString("L_EQUIP_2");
        //        export.WAREHOUSENUMBERDATA.L_EQUIP_3 = warehouse_struct.GetString("L_EQUIP_3");
        //        export.WAREHOUSENUMBERDATA.PLACEMENT = warehouse_struct.GetString("PLACEMENT"); //Cicor: If KA1 or KA5 => reserve LeNum
        //        _log.Debug("Placement: " + export.WAREHOUSENUMBERDATA.PLACEMENT); 
        //        export.WAREHOUSENUMBERDATA.UNITTYPE_1 = warehouse_struct.GetString("UNITTYPE_1");
        //        export.WAREHOUSENUMBERDATA.UNITTYPE_2 = warehouse_struct.GetString("UNITTYPE_2");
        //        export.WAREHOUSENUMBERDATA.UNITTYPE_3 = warehouse_struct.GetString("UNITTYPE_3");

        //        IRfcStructure salesdata_struct = func.GetStructure("SALESDATA");
        //        export.SALESDATA.SALES_ORG = salesdata_struct.GetString("SALES_ORG");
        //        export.SALESDATA.DISTR_CHAN = salesdata_struct.GetString("DISTR_CHAN");
        //        _log.Debug($"SALESSATA: ORG={export.SALESDATA.SALES_ORG} | CHAIN:{export.SALESDATA.DISTR_CHAN}"); 

        //        IRfcTable materialdescription_table = func.GetTable("MATERIALDESCRIPTION");
        //        _log.Debug($"MAT_GET_ALL: found {materialdescription_table.Count} rows in MATERIALDESCRIPTION"); 
        //        foreach (IRfcStructure row in materialdescription_table)
        //        {
        //            BAPI_MAKT_GA temp = new BAPI_MAKT_GA();
        //            temp.LANGU = row.GetString("LANGU");
        //            temp.LANGU_ISO = row.GetString("LANGU_ISO");
        //            temp.MATL_DESC = row.GetString("MATL_DESC");
        //            if (ConfigHelper.SapLanguage.Equals(temp.LANGU_ISO))
        //            {
        //                export.MATERIALDESCRIPTION.Add(temp);
        //                _log.Debug($"MATDESC: LANG={temp.LANGU}|{temp.LANGU_ISO} | MATL_DESC:{temp.MATL_DESC}"); 
        //            }
        //        }

        //        IRfcTable materialtext_table = func.GetTable("MATERIALTEXT");
        //        _log.Debug($"MAT_GET_ALL: found {materialtext_table.Count} rows in MATERIALTEXT"); 
        //        foreach (IRfcStructure row in materialtext_table)
        //        {
        //            BAPI_MLTX_GA temp = new BAPI_MLTX_GA();
        //            temp.APPLOBJECT = row.GetString("APPLOBJECT");
        //            temp.FORMAT_COL = row.GetString("FORMAT_COL");
        //            temp.LANGU = row.GetString("LANGU");
        //            temp.LANGU_ISO = row.GetString("LANGU_ISO");
        //            temp.TEXT_ID = row.GetString("TEXT_ID");
        //            temp.TEXT_LINE = row.GetString("TEXT_LINE");
        //            temp.TEXT_NAME = row.GetString("TEXT_NAME");
        //            if (ConfigHelper.SapLanguage.Equals(temp.LANGU_ISO))
        //            {
        //                export.MATERIALTEXT.Add(temp);
        //                _log.Debug($"MAT_GET_ALL MATTXT: APPLOBJ={temp.APPLOBJECT} | FORMATCOL:{temp.FORMAT_COL} | LANG:{temp.LANGU}|{temp.LANGU_ISO} | TEXT:{temp.TEXT_ID}|{temp.TEXT_LINE}|{temp.TEXT_NAME}"); 
        //            }
        //        }

        //        IRfcTable extension_table = func.GetTable("EXTENSIONOUT");
        //        _log.Debug($"MAT_GET_ALL: found {extension_table.Count} rows in EXTENSIONOUT"); 
        //        foreach (IRfcStructure row in extension_table)
        //        {
        //            BAPIPAREX temp = new BAPIPAREX();
        //            temp.STRUCTURE = row.GetString("STRUCTURE");
        //            temp.VALUEPART1 = row.GetString("VALUEPART1");
        //            temp.VALUEPART2 = row.GetString("VALUEPART2");
        //            temp.VALUEPART3 = row.GetString("VALUEPART3");
        //            temp.VALUEPART4 = row.GetString("VALUEPART4");
        //            export.EXTENSIONOUT.Add(temp);
        //            _log.Debug($"MAT_GET_ALL EXTENSIONOUT: STRUCT={temp.STRUCTURE} | VAL1:{temp.VALUEPART1} | VAL2:{temp.VALUEPART2}"); 
        //        }

        //        IRfcTable return_table = func.GetTable("RETURN");
        //        _log.Debug($"MAT_GET_ALL: found {return_table.Count} rows in RETURN"); 
        //        foreach (IRfcStructure row in return_table)
        //        {
        //            BAPIRETURN temp = new BAPIRETURN();
        //            temp.CODE = row.GetString("CODE");
        //            temp.LOG_MSG_NO = row.GetString("LOG_MSG_NO");
        //            temp.LOG_NO = row.GetString("LOG_NO");
        //            temp.MESSAGE = row.GetString("MESSAGE");
        //            temp.MESSAGE_V1 = row.GetString("MESSAGE_V1");
        //            temp.MESSAGE_V2 = row.GetString("MESSAGE_V2");
        //            temp.MESSAGE_V3 = row.GetString("MESSAGE_V3");
        //            temp.MESSAGE_V4 = row.GetString("MESSAGE_V4");
        //            export.RETURN.Add(temp);
        //            _log.Debug($"MAT_GET_ALL RETURN: Code={temp.CODE} | Msg:{temp.MESSAGE}"); 
        //        }
        //    }
        //    catch (Exception ex) { errorMsg += "CI: SAP Other Exception: " + ex; }

        //    if (!errorMsg.Equals("")) { _log.Debug(errorMsg); }

        //    return export;
        //}

        private static BAPI_BATCH_CREATE_EXPORT BAPI_BATCH_CREATE(BAPI_BATCH_CREATE_IMPORT import)
        {
            string errorMsg = "";
            BAPI_BATCH_CREATE_EXPORT export = new BAPI_BATCH_CREATE_EXPORT();

            try
            {
                StringBuilder ms = new StringBuilder();
                ms.Append($"Will now generate new Batch with the following Info:\n");
                ms.Append($"BATCHSTORAGELOCATION: {import.BATCHSTORAGELOCATION}\n");
                ms.Append($"MATERIAL: {import.MATERIAL}\n");
                ms.Append($"PLANT: {import.PLANT}\n");
                ms.Append($"VENDRBATCH: {import.BATCHATTRIBUTES.VENDRBATCH}\n");
                ms.Append($"VENDOR_NO: {import.BATCHATTRIBUTES.VENDOR_NO}\n");
                ms.Append($"PROD_DATE: {import.BATCHATTRIBUTES.PROD_DATE}\n");
                ms.Append($"ZZEMATN: {import.EXTENSION1.ZZEMATN}\n");
                ms.Append($"ZZMFRNR: {import.EXTENSION1.ZZMFRNR}\n");
                ms.Append($"ZZMFRPN: {import.EXTENSION1.ZZMFRPN}");
                _log.Debug(ms.ToString());

                RfcDestination dest = RfcDestinationManager.GetDestination(ConfigHelper.ActiveSapDestinationName);
                IRfcFunction func = dest.Repository.CreateFunction("BAPI_BATCH_CREATE");
                func.SetValue("BATCHSTORAGELOCATION", import.BATCHSTORAGELOCATION);
                func.SetValue("MATERIAL", import.MATERIAL.Trim().PadLeft(18, '0'));
                func.SetValue("PLANT", import.PLANT);
                IRfcStructure bapibatchatt = func.GetStructure("BATCHATTRIBUTES");
                bapibatchatt.SetValue("EXPIRYDATE", import.BATCHATTRIBUTES.EXPIRYDATE);
                bapibatchatt.SetValue("VENDOR_NO", import.BATCHATTRIBUTES.VENDOR_NO);
                bapibatchatt.SetValue("VENDRBATCH", import.BATCHATTRIBUTES.VENDRBATCH);
                bapibatchatt.SetValue("PROD_DATE", import.BATCHATTRIBUTES.PROD_DATE);
                IRfcStructure batchcontrolfields = func.GetStructure("BATCHCONTROLFIELDS");
                batchcontrolfields.SetValue("CLASS_NUM", "CHARGE_ELEKTR");
                batchcontrolfields.SetValue("DOCLASSIFY", "X");
                IRfcStructure extension1 = func.GetStructure("EXTENSION1");
                extension1.SetValue("ZZMFRNR", import.EXTENSION1.ZZMFRNR);
                extension1.SetValue("ZZMFRPN", import.EXTENSION1.ZZMFRPN);
                extension1.SetValue("ZZEMATN", import.EXTENSION1.ZZEMATN);
                func.Invoke(dest);

                export.BATCH = func.GetString("BATCH"); // Get Batch
                _log.Debug("Got new Batch from SAP: " + export.BATCH); 
                IRfcStructure bapibatchatt_export = func.GetStructure("BATCHATTRIBUTES");
                export.BATCHATTRIBUTES.AVAILABLE = bapibatchatt_export.GetString("AVAILABLE");
                export.BATCHATTRIBUTES.EXPIRYDATE = bapibatchatt_export.GetString("EXPIRYDATE");
                export.BATCHATTRIBUTES.STATUSKEY = bapibatchatt_export.GetString("STATUSKEY");
                export.BATCHATTRIBUTES.VENDOR_NO = bapibatchatt_export.GetString("VENDOR_NO");
                export.BATCHATTRIBUTES.VENDRBATCH = bapibatchatt_export.GetString("VENDRBATCH");
                export.BATCHATTRIBUTES.VAL_TYPE = bapibatchatt_export.GetString("VAL_TYPE");
                export.BATCHATTRIBUTES.LASTGRDATE = bapibatchatt_export.GetString("LASTGRDATE");
                export.BATCHATTRIBUTES.FREE_DATE1 = bapibatchatt_export.GetString("FREE_DATE1");
                export.BATCHATTRIBUTES.FREE_DATE2 = bapibatchatt_export.GetString("FREE_DATE2");
                export.BATCHATTRIBUTES.FREE_DATE3 = bapibatchatt_export.GetString("FREE_DATE3");
                export.BATCHATTRIBUTES.FREE_DATE4 = bapibatchatt_export.GetString("FREE_DATE4");
                export.BATCHATTRIBUTES.FREE_DATE5 = bapibatchatt_export.GetString("FREE_DATE5");
                export.BATCHATTRIBUTES.FREE_DATE6 = bapibatchatt_export.GetString("FREE_DATE6");
                export.BATCHATTRIBUTES.COUNTRYORI = bapibatchatt_export.GetString("COUNTRYORI");
                export.BATCHATTRIBUTES.COUNTRYORI_ISO = bapibatchatt_export.GetString("COUNTRYORI_ISO");
                export.BATCHATTRIBUTES.REGIONORIG = bapibatchatt_export.GetString("REGIONORIG");
                export.BATCHATTRIBUTES.EXPIMPGRP = bapibatchatt_export.GetString("EXPIMPGRP");
                export.BATCHATTRIBUTES.NEXTINSPEC = bapibatchatt_export.GetString("NEXTINSPEC");
                export.BATCHATTRIBUTES.PROD_DATE = bapibatchatt_export.GetString("PROD_DATE");
                export.BATCHATTRIBUTES.DEL_FLAG = bapibatchatt_export.GetString("DEL_FLAG");
                export.BATCHATTRIBUTES.STK_SEGMENT = bapibatchatt_export.GetString("STK_SEGMENT");
                export.BATCHATTRIBUTES.CERT_DATE = bapibatchatt_export.GetString("CERT_DATE");
                export.BATCHATTRIBUTES.STK_SEG_LONG = bapibatchatt_export.GetString("STK_SEG_LONG");

                IRfcTable ret_table = func.GetTable("RETURN");
                foreach (IRfcStructure row in ret_table)
                {
                    BAPIRET2 temp = new BAPIRET2();
                    temp.FIELD = ret_table.GetString("FIELD");
                    temp.ID = ret_table.GetString("ID");
                    temp.LOG_MSG_NO = ret_table.GetString("LOG_MSG_NO");
                    temp.LOG_NO = ret_table.GetString("LOG_NO");
                    temp.MESSAGE = ret_table.GetString("MESSAGE");
                    temp.MESSAGE_V1 = ret_table.GetString("MESSAGE_V1");
                    temp.MESSAGE_V2 = ret_table.GetString("MESSAGE_V2");
                    temp.MESSAGE_V3 = ret_table.GetString("MESSAGE_V3");
                    temp.MESSAGE_V4 = ret_table.GetString("MESSAGE_V4");
                    temp.NUMBER = ret_table.GetString("NUMBER");
                    temp.PARAMETER = ret_table.GetString("PARAMETER");
                    temp.ROW = ret_table.GetString("ROW");
                    temp.SYSTEM = ret_table.GetString("SYSTEM");
                    temp.TYPE = ret_table.GetString("TYPE");
                    export.RETURN.Add(temp);

                    _log.Debug($"Return ({temp.TYPE} | {temp.ID} | NUM:{temp.NUMBER}): " + temp.MESSAGE + $" | V1:{temp.MESSAGE_V1} | V2:{temp.MESSAGE_V2} | V3:{temp.MESSAGE_V3} | V4:{temp.MESSAGE_V4}"); 
                }
            }
            catch (Exception ex) { errorMsg += "CI: SAP Other Exception: " + ex; }

            if (!errorMsg.Equals("")) { _log.Debug(errorMsg); }

            return export;
        }

        private static BAPI_GOODSMVT_CREATE_EXPORT BAPI_GOODSMVT_CREATE(BAPI_GOODSMVT_CREATE_IMPORT import)
        {
            string errorMsg = "";
            BAPI_GOODSMVT_CREATE_EXPORT export = new BAPI_GOODSMVT_CREATE_EXPORT();

            try
            {
                RfcDestination dest = RfcDestinationManager.GetDestination(ConfigHelper.ActiveSapDestinationName);
                IRfcFunction func = dest.Repository.CreateFunction("BAPI_GOODSMVT_CREATE");
                IRfcStructure goodsmvt_header = func.GetStructure("GOODSMVT_HEADER");
                goodsmvt_header.SetValue("DOC_DATE", import.GOODSMVT_HEADER.DOC_DATE);
                goodsmvt_header.SetValue("PR_UNAME", import.GOODSMVT_HEADER.PR_UNAME);
                goodsmvt_header.SetValue("PSTNG_DATE", import.GOODSMVT_HEADER.PSTNG_DATE);
                goodsmvt_header.SetValue("REF_DOC_NO", import.GOODSMVT_HEADER.REF_DOC_NO);
                //goodsmvt_header.SetValue("ELIKZ", " ");
                //goodsmvt_header.SetValue("VER_GR_GI_SLIP", "2");
                //goodsmvt_header.SetValue("VER_GR_GI_SLIPX", "X");
                func.GetStructure("GOODSMVT_CODE").SetValue("GM_CODE", import.GOODSMVT_CODE.GM_CODE);
                IRfcTable goodsmvt_item = func.GetTable("GOODSMVT_ITEM");

                _log.Debug($"GOODSMVT: Will transmit {import.GOODSMVT_ITEM.Count} reels to SAP");
                foreach (BAPI2017_GM_ITEM_CREATE item in import.GOODSMVT_ITEM)
                {
                    goodsmvt_item.Append();
                    //goodsmvt_header.SetValue("NO_MORE_GR", " ");
                    if (item.DELIV_ITEM != null && !item.BATCH.Trim().Equals("")) { goodsmvt_item.SetValue("BATCH", item.BATCH); }
                    if (item.DELIV_ITEM != null && !item.DELIV_ITEM.Trim().Equals("")) { goodsmvt_item.SetValue("DELIV_ITEM", item.DELIV_ITEM); }
                    if (item.DELIV_NUMB != null && !item.DELIV_NUMB.Trim().Equals("")) { goodsmvt_item.SetValue("DELIV_NUMB", item.DELIV_NUMB); }
                    goodsmvt_item.SetValue("ENTRY_QNT", item.ENTRY_QNT); 
                    if (item.ENTRY_UOM != null && !item.ENTRY_UOM.Trim().Equals("")) { goodsmvt_item.SetValue("ENTRY_UOM", item.ENTRY_UOM); }
                    if (item.ENTRY_UOM_ISO != null && !item.ENTRY_UOM_ISO.Trim().Equals("")) { goodsmvt_item.SetValue("ENTRY_UOM_ISO", item.ENTRY_UOM_ISO); }
                    if (item.EXPIRYDATE != null && !item.EXPIRYDATE.Trim().Equals("")) { goodsmvt_item.SetValue("EXPIRYDATE", item.EXPIRYDATE); }
                    if (item.ITEM_TEXT != null && !item.ITEM_TEXT.Trim().Equals("")) { goodsmvt_item.SetValue("ITEM_TEXT", item.ITEM_TEXT); }
                    if (item.MATERIAL != null && !item.MATERIAL.Trim().Equals("")) { goodsmvt_item.SetValue("MATERIAL", item.MATERIAL); }
                    if (item.MOVE_BATCH != null && !item.MOVE_BATCH.Trim().Equals("")) { goodsmvt_item.SetValue("MOVE_BATCH", item.MOVE_BATCH); }
                    if (item.MOVE_PLANT != null && !item.MOVE_PLANT.Trim().Equals("")) { goodsmvt_item.SetValue("MOVE_PLANT", item.MOVE_PLANT); }
                    if (item.MOVE_STLOC != null && !item.MOVE_STLOC.Trim().Equals("")) { goodsmvt_item.SetValue("MOVE_STLOC", item.MOVE_STLOC); }
                    if (item.MOVE_TYPE != null && !item.MOVE_TYPE.Trim().Equals("")) { goodsmvt_item.SetValue("MOVE_TYPE", item.MOVE_TYPE); }
                    if (item.MVT_IND != null && !item.MVT_IND.Trim().Equals("")) { goodsmvt_item.SetValue("MVT_IND", item.MVT_IND); }
                    if (item.NO_TRANSFER_REQ != null && !item.NO_TRANSFER_REQ.Trim().Equals("")) { goodsmvt_item.SetValue("NO_TRANSFER_REQ", item.NO_TRANSFER_REQ); }
                    if (item.PLANT != null && !item.PLANT.Trim().Equals("")) { goodsmvt_item.SetValue("PLANT", item.PLANT); }
                    if (item.PO_ITEM != null && !item.PO_ITEM.Trim().Equals("")) { goodsmvt_item.SetValue("PO_ITEM", item.PO_ITEM.PadLeft(5, '0')); }
                    if (item.PO_NUMBER != null && !item.PO_NUMBER.Trim().Equals("")) { goodsmvt_item.SetValue("PO_NUMBER", item.PO_NUMBER); }
                    if (item.SPEC_STOCK != null && !item.SPEC_STOCK.Trim().Equals("")) { goodsmvt_item.SetValue("SPEC_STOCK", item.SPEC_STOCK); }
                    if (item.STCK_TYPE != null && !item.STCK_TYPE.Trim().Equals("")) { goodsmvt_item.SetValue("STCK_TYPE", item.STCK_TYPE); }
                    if (item.STGE_LOC != null && !item.STGE_LOC.Trim().Equals("")) { goodsmvt_item.SetValue("STGE_LOC", item.STGE_LOC); }
                    if (item.VENDOR != null && !item.VENDOR.Trim().Equals("")) { goodsmvt_item.SetValue("VENDOR", item.VENDOR); }
                    _log.Debug($"GOODSMVT: Will transmit reel => MATERIAL:{item.MATERIAL}, QNT:{item.ENTRY_QNT}");
                }
                func.Invoke(dest);

                export.MATDOCUMENTYEAR = func.GetString("MATDOCUMENTYEAR");
                export.MATERIALDOCUMENT = func.GetString("MATERIALDOCUMENT");

                _log.Debug($"GOODSMVT_CREATE: MATERIALDOCUMENTYEAR={export.MATDOCUMENTYEAR} MATERIALDOCUMENT={export.MATERIALDOCUMENT}"); 

                IRfcTable ret_table = func.GetTable("RETURN");
                foreach (IRfcStructure row in ret_table)
                {
                    BAPIRET2 temp = new BAPIRET2();
                    temp.FIELD = ret_table.GetString("FIELD");
                    temp.ID = ret_table.GetString("ID");
                    temp.LOG_MSG_NO = ret_table.GetString("LOG_MSG_NO");
                    temp.LOG_NO = ret_table.GetString("LOG_NO");
                    temp.MESSAGE = ret_table.GetString("MESSAGE");
                    temp.MESSAGE_V1 = ret_table.GetString("MESSAGE_V1");
                    temp.MESSAGE_V2 = ret_table.GetString("MESSAGE_V2");
                    temp.MESSAGE_V3 = ret_table.GetString("MESSAGE_V3");
                    temp.MESSAGE_V4 = ret_table.GetString("MESSAGE_V4");
                    temp.NUMBER = ret_table.GetString("NUMBER");
                    temp.PARAMETER = ret_table.GetString("PARAMETER");
                    temp.ROW = ret_table.GetString("ROW");
                    temp.SYSTEM = ret_table.GetString("SYSTEM");
                    temp.TYPE = ret_table.GetString("TYPE");
                    export.RETURN.Add(temp);

                    _log.Debug($"Return ({temp.TYPE} | {temp.ID} | NUM:{temp.NUMBER}): " + temp.MESSAGE + $" | V1:{temp.MESSAGE_V1} | V2:{temp.MESSAGE_V2} | V3:{temp.MESSAGE_V3} | V4:{temp.MESSAGE_V4}"); 
                }
            }
            catch (Exception ex) { errorMsg += "SAP Other Exception: " + ex; export.RETURN.Add(new BAPIRET2() { TYPE = "E", MESSAGE = ex.ToString() }); }

            if (!errorMsg.Equals("")) { _log.Error(errorMsg); }

            return export;
        }

        private static BAPI_GOODSMVT_CREATE_EXPORT BAPI_GOODSMVT_CREATE_WithDirectCommit(BAPI_GOODSMVT_CREATE_IMPORT import)
        {
            string errorMsg = "";
            BAPI_GOODSMVT_CREATE_EXPORT export = new BAPI_GOODSMVT_CREATE_EXPORT();

            try
            {
                RfcDestination dest = RfcDestinationManager.GetDestination(ConfigHelper.ActiveSapDestinationName);
                IRfcFunction func = dest.Repository.CreateFunction("BAPI_GOODSMVT_CREATE");
                IRfcStructure goodsmvt_header = func.GetStructure("GOODSMVT_HEADER");
                goodsmvt_header.SetValue("DOC_DATE", import.GOODSMVT_HEADER.DOC_DATE);
                goodsmvt_header.SetValue("PR_UNAME", import.GOODSMVT_HEADER.PR_UNAME);
                goodsmvt_header.SetValue("PSTNG_DATE", import.GOODSMVT_HEADER.PSTNG_DATE);
                goodsmvt_header.SetValue("REF_DOC_NO", import.GOODSMVT_HEADER.REF_DOC_NO);
                func.GetStructure("GOODSMVT_CODE").SetValue("GM_CODE", import.GOODSMVT_CODE.GM_CODE);
                IRfcTable goodsmvt_item = func.GetTable("GOODSMVT_ITEM");

                _log.Debug($"GOODSMVT: Will transmit {import.GOODSMVT_ITEM.Count} reels to SAP");
                foreach (BAPI2017_GM_ITEM_CREATE item in import.GOODSMVT_ITEM)
                {
                    goodsmvt_item.Append();
                    //goodsmvt_header.SetValue("NO_MORE_GR", " ");
                    if (item.DELIV_ITEM != null && !item.BATCH.Trim().Equals(""))               { goodsmvt_item.SetValue("BATCH", item.BATCH); }
                    if (item.DELIV_ITEM != null && !item.DELIV_ITEM.Trim().Equals(""))          { goodsmvt_item.SetValue("DELIV_ITEM", item.DELIV_ITEM); }
                    if (item.DELIV_NUMB != null && !item.DELIV_NUMB.Trim().Equals(""))          { goodsmvt_item.SetValue("DELIV_NUMB", item.DELIV_NUMB); }
                                                                                                  goodsmvt_item.SetValue("ENTRY_QNT", item.ENTRY_QNT);
                    if (item.ENTRY_UOM != null && !item.ENTRY_UOM.Trim().Equals(""))            { goodsmvt_item.SetValue("ENTRY_UOM", item.ENTRY_UOM); }
                    if (item.ENTRY_UOM_ISO != null && !item.ENTRY_UOM_ISO.Trim().Equals(""))    { goodsmvt_item.SetValue("ENTRY_UOM_ISO", item.ENTRY_UOM_ISO); }
                    if (item.EXPIRYDATE != null && !item.EXPIRYDATE.Trim().Equals(""))          { goodsmvt_item.SetValue("EXPIRYDATE", item.EXPIRYDATE); }
                    if (item.ITEM_TEXT != null && !item.ITEM_TEXT.Trim().Equals(""))            { goodsmvt_item.SetValue("ITEM_TEXT", item.ITEM_TEXT); }
                    if (item.MATERIAL != null && !item.MATERIAL.Trim().Equals(""))              { goodsmvt_item.SetValue("MATERIAL", item.MATERIAL); }
                    if (item.MOVE_BATCH != null && !item.MOVE_BATCH.Trim().Equals(""))          { goodsmvt_item.SetValue("MOVE_BATCH", item.MOVE_BATCH); }
                    if (item.MOVE_PLANT != null && !item.MOVE_PLANT.Trim().Equals(""))          { goodsmvt_item.SetValue("MOVE_PLANT", item.MOVE_PLANT); }
                    if (item.MOVE_STLOC != null && !item.MOVE_STLOC.Trim().Equals(""))          { goodsmvt_item.SetValue("MOVE_STLOC", item.MOVE_STLOC); }
                    if (item.MOVE_TYPE != null && !item.MOVE_TYPE.Trim().Equals(""))            { goodsmvt_item.SetValue("MOVE_TYPE", item.MOVE_TYPE); }
                    if (item.MVT_IND != null && !item.MVT_IND.Trim().Equals(""))                { goodsmvt_item.SetValue("MVT_IND", item.MVT_IND); }
                    if (item.NO_TRANSFER_REQ != null && !item.NO_TRANSFER_REQ.Trim().Equals("")){ goodsmvt_item.SetValue("NO_TRANSFER_REQ", item.NO_TRANSFER_REQ); }
                    if (item.PLANT != null && !item.PLANT.Trim().Equals(""))                    { goodsmvt_item.SetValue("PLANT", item.PLANT); }
                    if (item.PO_ITEM != null && !item.PO_ITEM.Trim().Equals(""))                { goodsmvt_item.SetValue("PO_ITEM", item.PO_ITEM); }
                    if (item.PO_NUMBER != null && !item.PO_NUMBER.Trim().Equals(""))            { goodsmvt_item.SetValue("PO_NUMBER", item.PO_NUMBER); }
                    if (item.SPEC_STOCK != null && !item.SPEC_STOCK.Trim().Equals(""))          { goodsmvt_item.SetValue("SPEC_STOCK", item.SPEC_STOCK); }
                    if (item.STCK_TYPE != null && !item.STCK_TYPE.Trim().Equals(""))            { goodsmvt_item.SetValue("STCK_TYPE", item.STCK_TYPE); }
                    if (item.STGE_LOC != null && !item.STGE_LOC.Trim().Equals(""))              { goodsmvt_item.SetValue("STGE_LOC", item.STGE_LOC); }
                    if (item.VENDOR != null && !item.VENDOR.Trim().Equals(""))                  { goodsmvt_item.SetValue("VENDOR", item.VENDOR); }
                    _log.Debug($"GOODSMVT: Will transmit reel => MATERIAL:{item.MATERIAL}, QNT:{item.ENTRY_QNT}");
                }
                func.Invoke(dest);

                export.MATDOCUMENTYEAR = func.GetString("MATDOCUMENTYEAR");
                export.MATERIALDOCUMENT = func.GetString("MATERIALDOCUMENT");

                _log.Debug($"GOODSMVT_CREATE: MATERIALDOCUMENTYEAR={export.MATDOCUMENTYEAR} MATERIALDOCUMENT={export.MATERIALDOCUMENT}");

                IRfcTable ret_table = func.GetTable("RETURN");
                foreach (IRfcStructure row in ret_table)
                {
                    BAPIRET2 temp = new BAPIRET2();
                    temp.FIELD = ret_table.GetString("FIELD");
                    temp.ID = ret_table.GetString("ID");
                    temp.LOG_MSG_NO = ret_table.GetString("LOG_MSG_NO");
                    temp.LOG_NO = ret_table.GetString("LOG_NO");
                    temp.MESSAGE = ret_table.GetString("MESSAGE");
                    temp.MESSAGE_V1 = ret_table.GetString("MESSAGE_V1");
                    temp.MESSAGE_V2 = ret_table.GetString("MESSAGE_V2");
                    temp.MESSAGE_V3 = ret_table.GetString("MESSAGE_V3");
                    temp.MESSAGE_V4 = ret_table.GetString("MESSAGE_V4");
                    temp.NUMBER = ret_table.GetString("NUMBER");
                    temp.PARAMETER = ret_table.GetString("PARAMETER");
                    temp.ROW = ret_table.GetString("ROW");
                    temp.SYSTEM = ret_table.GetString("SYSTEM");
                    temp.TYPE = ret_table.GetString("TYPE");
                    export.RETURN.Add(temp);

                    _log.Debug($"Return ({temp.TYPE} | {temp.ID} | NUM:{temp.NUMBER}): " + temp.MESSAGE + $" | V1:{temp.MESSAGE_V1} | V2:{temp.MESSAGE_V2} | V3:{temp.MESSAGE_V3} | V4:{temp.MESSAGE_V4}");
                }


                //---------------------------------------------------------------------------------------------------------------------

                Thread.Sleep(1000);
                IRfcFunction func2 = dest.Repository.CreateFunction("BAPI_TRANSACTION_COMMIT");
                func2.SetValue("WAIT", "X");
                func2.Invoke(dest);
                try
                {
                    IRfcStructure ret_table2 = func2.GetStructure("RETURN");
                    if (ret_table2 == null) { _log.Debug($"Attention: Return table of BAPI_TRANSACTION_COMMIT is NULL!!!"); }
                    else
                    {
                        BAPIRET2 temp = new BAPIRET2();
                        temp.FIELD = ret_table2.GetString("FIELD") ?? "";
                        temp.ID = ret_table2.GetString("ID") ?? "";
                        temp.LOG_MSG_NO = ret_table2.GetString("LOG_MSG_NO") ?? "";
                        temp.LOG_NO = ret_table2.GetString("LOG_NO") ?? "";
                        temp.MESSAGE = ret_table2.GetString("MESSAGE") ?? "";
                        temp.MESSAGE_V1 = ret_table2.GetString("MESSAGE_V1") ?? "";
                        temp.MESSAGE_V2 = ret_table2.GetString("MESSAGE_V2") ?? "";
                        temp.MESSAGE_V3 = ret_table2.GetString("MESSAGE_V3") ?? "";
                        temp.MESSAGE_V4 = ret_table2.GetString("MESSAGE_V4") ?? "";
                        temp.NUMBER = ret_table2.GetString("NUMBER") ?? "";
                        temp.PARAMETER = ret_table2.GetString("PARAMETER") ?? "";
                        temp.ROW = ret_table2.GetString("ROW") ?? "";
                        temp.SYSTEM = ret_table2.GetString("SYSTEM") ?? "";
                        temp.TYPE = ret_table2.GetString("TYPE") ?? "";
                        export.RETURN.Add(temp);
                        _log.Debug($"Return of BAPI_TRANSACTION_COMMIT ({temp.TYPE} | {temp.ID} | NUM:{temp.NUMBER}): " + temp.MESSAGE + $" | V1:{temp.MESSAGE_V1} | V2:{temp.MESSAGE_V2} | V3:{temp.MESSAGE_V3} | V4:{temp.MESSAGE_V4}");
                    }
                }
                catch (Exception e) { _log.Error($"Could not load RETURN of BAPI_TRANSACTION_COMMIT => {e}"); }
            }
            catch (Exception ex) { errorMsg += "SAP Other Exception: " + ex; export.RETURN.Add(new BAPIRET2() { TYPE = "E", MESSAGE = ex.ToString() }); }

            if (!errorMsg.Equals("")) { _log.Error(errorMsg); }

            return export;
        }

        private static BAPI_GOODSMVT_CREATE_EXPORT ZBAPI_GOODSMVT_CREATE(BAPI_GOODSMVT_CREATE_IMPORT import)
        {
            string errorMsg = "";
            BAPI_GOODSMVT_CREATE_EXPORT export = new BAPI_GOODSMVT_CREATE_EXPORT();

            try
            {
                RfcDestination dest = RfcDestinationManager.GetDestination(ConfigHelper.ActiveSapDestinationName);
                IRfcFunction func = dest.Repository.CreateFunction("ZBAPI_GOODSMVT_CREATE");
                IRfcStructure goodsmvt_header = func.GetStructure("GOODSMVT_HEADER");
                goodsmvt_header.SetValue("DOC_DATE", import.GOODSMVT_HEADER.DOC_DATE);
                goodsmvt_header.SetValue("PR_UNAME", import.GOODSMVT_HEADER.PR_UNAME);
                goodsmvt_header.SetValue("PSTNG_DATE", import.GOODSMVT_HEADER.PSTNG_DATE);
                goodsmvt_header.SetValue("REF_DOC_NO", import.GOODSMVT_HEADER.REF_DOC_NO);
                func.GetStructure("GOODSMVT_CODE").SetValue("GM_CODE", import.GOODSMVT_CODE.GM_CODE);
                IRfcTable goodsmvt_item = func.GetTable("GOODSMVT_ITEM");

                _log.Debug($"GOODSMVT: Will transmit {import.GOODSMVT_ITEM.Count} reels to SAP");
                foreach (BAPI2017_GM_ITEM_CREATE item in import.GOODSMVT_ITEM)
                {
                    goodsmvt_item.Append();
                    //goodsmvt_header.SetValue("NO_MORE_GR", " ");
                    if (item.DELIV_ITEM != null && !item.BATCH.Trim().Equals("")) { goodsmvt_item.SetValue("BATCH", item.BATCH); }
                    if (item.DELIV_ITEM != null && !item.DELIV_ITEM.Trim().Equals("")) { goodsmvt_item.SetValue("DELIV_ITEM", item.DELIV_ITEM); }
                    if (item.DELIV_NUMB != null && !item.DELIV_NUMB.Trim().Equals("")) { goodsmvt_item.SetValue("DELIV_NUMB", item.DELIV_NUMB); }
                    goodsmvt_item.SetValue("ENTRY_QNT", item.ENTRY_QNT);
                    if (item.ENTRY_UOM != null && !item.ENTRY_UOM.Trim().Equals("")) { goodsmvt_item.SetValue("ENTRY_UOM", item.ENTRY_UOM); }
                    if (item.ENTRY_UOM_ISO != null && !item.ENTRY_UOM_ISO.Trim().Equals("")) { goodsmvt_item.SetValue("ENTRY_UOM_ISO", item.ENTRY_UOM_ISO); }
                    if (item.EXPIRYDATE != null && !item.EXPIRYDATE.Trim().Equals("")) { goodsmvt_item.SetValue("EXPIRYDATE", item.EXPIRYDATE); }
                    if (item.ITEM_TEXT != null && !item.ITEM_TEXT.Trim().Equals("")) { goodsmvt_item.SetValue("ITEM_TEXT", item.ITEM_TEXT); }
                    if (item.MATERIAL != null && !item.MATERIAL.Trim().Equals("")) { goodsmvt_item.SetValue("MATERIAL", item.MATERIAL); }
                    if (item.MOVE_BATCH != null && !item.MOVE_BATCH.Trim().Equals("")) { goodsmvt_item.SetValue("MOVE_BATCH", item.MOVE_BATCH); }
                    if (item.MOVE_PLANT != null && !item.MOVE_PLANT.Trim().Equals("")) { goodsmvt_item.SetValue("MOVE_PLANT", item.MOVE_PLANT); }
                    if (item.MOVE_STLOC != null && !item.MOVE_STLOC.Trim().Equals("")) { goodsmvt_item.SetValue("MOVE_STLOC", item.MOVE_STLOC); }
                    if (item.MOVE_TYPE != null && !item.MOVE_TYPE.Trim().Equals("")) { goodsmvt_item.SetValue("MOVE_TYPE", item.MOVE_TYPE); }
                    if (item.MVT_IND != null && !item.MVT_IND.Trim().Equals("")) { goodsmvt_item.SetValue("MVT_IND", item.MVT_IND); }
                    if (item.NO_TRANSFER_REQ != null && !item.NO_TRANSFER_REQ.Trim().Equals("")) { goodsmvt_item.SetValue("NO_TRANSFER_REQ", item.NO_TRANSFER_REQ); }
                    if (item.PLANT != null && !item.PLANT.Trim().Equals("")) { goodsmvt_item.SetValue("PLANT", item.PLANT); }
                    if (item.PO_ITEM != null && !item.PO_ITEM.Trim().Equals("")) { goodsmvt_item.SetValue("PO_ITEM", item.PO_ITEM); }
                    if (item.PO_NUMBER != null && !item.PO_NUMBER.Trim().Equals("")) { goodsmvt_item.SetValue("PO_NUMBER", item.PO_NUMBER); }
                    if (item.SPEC_STOCK != null && !item.SPEC_STOCK.Trim().Equals("")) { goodsmvt_item.SetValue("SPEC_STOCK", item.SPEC_STOCK); }
                    if (item.STCK_TYPE != null && !item.STCK_TYPE.Trim().Equals("")) { goodsmvt_item.SetValue("STCK_TYPE", item.STCK_TYPE); }
                    if (item.STGE_LOC != null && !item.STGE_LOC.Trim().Equals("")) { goodsmvt_item.SetValue("STGE_LOC", item.STGE_LOC); }
                    if (item.VENDOR != null && !item.VENDOR.Trim().Equals("")) { goodsmvt_item.SetValue("VENDOR", item.VENDOR); }
                    _log.Debug($"GOODSMVT: Will transmit reel => MATERIAL:{item.MATERIAL}, QNT:{item.ENTRY_QNT}");
                }
                func.Invoke(dest);

                export.MATDOCUMENTYEAR = func.GetString("MATDOCUMENTYEAR");
                export.MATERIALDOCUMENT = func.GetString("MATERIALDOCUMENT");

                _log.Debug($"ZBAPI_GOODSMVT_CREATE: MATERIALDOCUMENTYEAR={export.MATDOCUMENTYEAR} MATERIALDOCUMENT={export.MATERIALDOCUMENT}");

                IRfcTable ret_table = func.GetTable("RETURN");
                foreach (IRfcStructure row in ret_table)
                {
                    BAPIRET2 temp = new BAPIRET2();
                    temp.FIELD = ret_table.GetString("FIELD");
                    temp.ID = ret_table.GetString("ID");
                    temp.LOG_MSG_NO = ret_table.GetString("LOG_MSG_NO");
                    temp.LOG_NO = ret_table.GetString("LOG_NO");
                    temp.MESSAGE = ret_table.GetString("MESSAGE");
                    temp.MESSAGE_V1 = ret_table.GetString("MESSAGE_V1");
                    temp.MESSAGE_V2 = ret_table.GetString("MESSAGE_V2");
                    temp.MESSAGE_V3 = ret_table.GetString("MESSAGE_V3");
                    temp.MESSAGE_V4 = ret_table.GetString("MESSAGE_V4");
                    temp.NUMBER = ret_table.GetString("NUMBER");
                    temp.PARAMETER = ret_table.GetString("PARAMETER");
                    temp.ROW = ret_table.GetString("ROW");
                    temp.SYSTEM = ret_table.GetString("SYSTEM");
                    temp.TYPE = ret_table.GetString("TYPE");
                    export.RETURN.Add(temp);

                    _log.Debug($"Return ({temp.TYPE} | {temp.ID} | NUM:{temp.NUMBER}): " + temp.MESSAGE + $" | V1:{temp.MESSAGE_V1} | V2:{temp.MESSAGE_V2} | V3:{temp.MESSAGE_V3} | V4:{temp.MESSAGE_V4}");
                }
            }
            catch (Exception ex) { errorMsg += "SAP Other Exception: " + ex; export.RETURN.Add(new BAPIRET2() { TYPE = "E", MESSAGE = ex.ToString() }); }

            if (!errorMsg.Equals("")) { _log.Error(errorMsg); }

            return export;
        }

        private static BAPI_TRANSACTION_COMMIT_EXPORT BAPI_TRANSACTION_COMMIT() //BAPI_TRANSACTION_COMMIT_IMPORT import ???
        {
            string errorMsg = "";
            BAPI_TRANSACTION_COMMIT_EXPORT export = new BAPI_TRANSACTION_COMMIT_EXPORT();
            _log.Debug($"Will try to execute BAPI_TRANSACTION_COMMIT"); 

            try
            { 
                RfcDestination dest = RfcDestinationManager.GetDestination(ConfigHelper.ActiveSapDestinationName);
                IRfcFunction func = dest.Repository.CreateFunction("BAPI_TRANSACTION_COMMIT");
                func.SetValue("WAIT", "X");
                func.Invoke(dest);

                try
                {
                    IRfcStructure ret_table = func.GetStructure("RETURN");
                    BAPIRET2 temp = new BAPIRET2();
                    temp.FIELD = ret_table.GetString("FIELD");
                    temp.ID = ret_table.GetString("ID");
                    temp.LOG_MSG_NO = ret_table.GetString("LOG_MSG_NO");
                    temp.LOG_NO = ret_table.GetString("LOG_NO");
                    temp.MESSAGE = ret_table.GetString("MESSAGE");
                    temp.MESSAGE_V1 = ret_table.GetString("MESSAGE_V1");
                    temp.MESSAGE_V2 = ret_table.GetString("MESSAGE_V2");
                    temp.MESSAGE_V3 = ret_table.GetString("MESSAGE_V3");
                    temp.MESSAGE_V4 = ret_table.GetString("MESSAGE_V4");
                    temp.NUMBER = ret_table.GetString("NUMBER");
                    temp.PARAMETER = ret_table.GetString("PARAMETER");
                    temp.ROW = ret_table.GetString("ROW");
                    temp.SYSTEM = ret_table.GetString("SYSTEM");
                    temp.TYPE = ret_table.GetString("TYPE");
                    export.RETURN.Add(temp);
                    _log.Debug($"Return of BAPI_TRANSACTION_COMMIT ({temp.TYPE} | {temp.ID} | NUM:{temp.NUMBER}): " + temp.MESSAGE + $" | V1:{temp.MESSAGE_V1} | V2:{temp.MESSAGE_V2} | V3:{temp.MESSAGE_V3} | V4:{temp.MESSAGE_V4}");
                }
                catch (Exception e) { _log.Error($"Could not load RETURN of BAPI_TRANSACTION_COMMIT => {e}"); }
            }
            catch (Exception ex) { errorMsg += "SAP Other Exception: " + ex; }

            if (!errorMsg.Equals("")) { _log.Debug(errorMsg); }

            return export;
        }

        private static CLAF_CLASSIFICATION_OF_OBJECTS_EXPORT CLAF_CLASSIFICATION_OF_OBJECTS(CLAF_CLASSIFICATION_OF_OBJECTS_IMPORT import)
        {
            string errorMsg = "";
            CLAF_CLASSIFICATION_OF_OBJECTS_EXPORT export = new CLAF_CLASSIFICATION_OF_OBJECTS_EXPORT();

            try
            {
                RfcDestination dest = RfcDestinationManager.GetDestination(ConfigHelper.ActiveSapDestinationName);
                IRfcFunction func = dest.Repository.CreateFunction("CLAF_CLASSIFICATION_OF_OBJECTS");
                func.SetValue("CLASS", import.CLASS);
                func.SetValue("CLASSTYPE", import.CLASSTYPE);
                func.SetValue("INHERITED_CHAR", import.INHERITED_CHAR);
                func.SetValue("LANGUAGE", import.LANGUAGE);
                func.SetValue("OBJECT", import.OBJECT);
                func.SetValue("OBJECTTABLE", import.OBJECTTABLE);
                func.SetValue("CLASSTEXT", "X");
                func.SetValue("INITIAL_CHARACT", "X");
                func.Invoke(dest);

                IRfcTable t_objects_table = func.GetTable("T_OBJECTDATA");
                foreach (IRfcStructure row in t_objects_table)
                {
                    export.T_OBJECTDATA.Add(new CLOBJDAT()
                    {
                        TABIX = row.GetInt("TABIX"),
                        POSNR = row.GetString("POSNR"),
                        SMBEZ = row.GetString("SMBEZ"),
                        ZAEHL = row.GetString("ZAEHL"),
                        OPER1 = row.GetString("OPER1"),
                        AUSP1 = row.GetString("AUSP1"),
                        DIME1 = row.GetString("DIME1"),
                        ATFLV = row.GetFloat("ATFLV"),
                        OPER2 = row.GetString("OPER2"),
                        AUSP2 = row.GetString("AUSP2"),
                        DIME2 = row.GetString("DIME2"),
                        ATNAM = row.GetString("ATNAM"),
                        INHER = row.GetString("INHER"),
                        VCLINT = row.GetString("VCLINT"),
                        ATVGLART = row.GetString("ATVGLART"),
                        ATZIS = row.GetString("ATZIS")
                    });
                }
            }
            catch (Exception ex) { errorMsg += "CI: SAP Other Exception: " + ex; }

            if (!errorMsg.Equals("")) { _log.Error(errorMsg); }

            return export;
        }
        private static BAPI_OBJCL_GET_KEY_OF_OBJECT_EXPORT BAPI_OBJCL_GET_KEY_OF_OBJECT(BAPI_OBJCL_GET_KEY_OF_OBJECT_IMPORT import)
        {
            string errorMsg = "";
            BAPI_OBJCL_GET_KEY_OF_OBJECT_EXPORT export = new BAPI_OBJCL_GET_KEY_OF_OBJECT_EXPORT();
            string OBJECTNAME = import.MATNR?.Trim().PadLeft(18, '0') + import.MATNR?.Trim().PadLeft(10, '0'); //Create Objectname based on MATNR and CHARG (with '0' in front)

            try
            {
                RfcDestination dest = RfcDestinationManager.GetDestination(ConfigHelper.ActiveSapDestinationName);
                IRfcFunction func = dest.Repository.CreateFunction("BAPI_OBJCL_GET_KEY_OF_OBJECT");
                func.SetValue("CLASSTYPE", import.CLASSTYPE);
                func.SetValue("OBJECTNAME", OBJECTNAME);
                func.SetValue("OBJECTTABLE", import.OBJECTTABLE);
                func.Invoke(dest);

                export.CLOBJECTKEYOUT = func.GetString("CLOBJECTKEYOUT");
            }
            catch (Exception ex) { errorMsg += "CI: SAP Other Exception: " + ex; }

            if (!errorMsg.Equals("")) { _log.Debug(errorMsg); }

            return export;
        }
    }
}
