Imports System.IO
Imports System.Threading
Imports IntraSell_DLL
Imports IntraSell_Net_Base
Imports MySql.Data.MySqlClient

Public Module ModuleBuchVorgang

    Public PREIS_GENAUIGKEIT As Integer = 4

    ''' <summary>
    ''' Berechnungsmethode für MWST bei Vorgang Summen, bei der Brutto Method wird die Summe der Bruttopreise der einzehlnen Position berechnet und dann die je MWST Klasse eine NEtto Summe gebildet die zusammengerechnet wird
    ''' </summary>
    Const BRUTTO_METHODE = True

    Public Const BARGELD_GEGEBEN = "Bargeld_gegeben"
    Public Const BARGELD_RESTO = "Bargeld_resto"
    Public Const GUTSCHRIFT_BETRAG_EIGENSCHAFT = "Gutschrift_Betrag"

    Public frmCollection As New Collection
    Private DictionaryVorgangStatusColor As New Dictionary(Of String, Color)

    ''' <summary>
    ''' Event nachdem ein Vorgang abgeschlossen wurde
    ''' </summary>
    ''' <param name="Endsume"></param>
    Public Event VorgangAbgeschlossen(Endsume As Decimal)

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="msg"></param>
    ''' <param name="Style"></param>
    Public Event PostMsgEvent(msg As String, Style As MsgBoxStyle)

    ''' <summary>
    ''' Die Kueche wird beauftragt 
    ''' </summary>
    ''' <param name="vorgang"></param>
    ''' <param name="auftrag"></param>
    Public Event VorgangKuecheEvent(vorgang As VorgangInBearbeitung, auftrag As String)

    Private localeSettings As New ClassSettings

    Function IstVorgangTyp(Typ As String)
        Return VorgangTypen.AN = Typ _
        OrElse VorgangTypen.AU = Typ _
        OrElse VorgangTypen.AR = Typ _
        OrElse VorgangTypen.GU = Typ _
        OrElse VorgangTypen.RE = Typ _
        OrElse VorgangTypen.LI = Typ _
        OrElse VorgangTypen.LE = Typ _
        OrElse VorgangTypen.LA = Typ _
        OrElse VorgangTypen.LAU = Typ _
        OrElse VorgangTypen.KU = Typ
    End Function

    Function IsBarVorgang(Typ As String, Nummer As Integer) As Boolean
        Return (Typ = VorgangTypen.AR AndAlso IsNumeric(intrasell.vorgang.GetVorgangEigenschaft(Typ, Nummer, BARGELD_GEGEBEN)))
    End Function

    ''' <summary>
    ''' Neuer Vorgang mit Kundeneinstellungen einreichen 
    ''' </summary>
    ''' <param name="Vorgang"></param>
    ''' <param name="IDNR"></param>
    ''' <param name="Vorgangtyp"></param>
    ''' <remarks></remarks>
    Sub NeuerVorgang(ByRef Vorgang As dsVorgaenge.buchvorgangRow, IDNR As Integer, Vorgangtyp As String, Datum As Date)
        Vorgang.KundNr = IDNR
        Vorgang.Typ = Vorgangtyp
        Vorgang.Nummer = intrasell.vorgang.GetNewVorgangNummer(Vorgangtyp, IDNR)
        Vorgang.Datum = Datum
        Vorgang.MitarbeiterNr = MitarbeiterID

        Dim mandant = FirstRow("select mandant from ofAdressen where idnr=" & Vorgang.KundNr)
        If Not IsDBNull(mandant) Then
            Vorgang.MandantNr = mandant
        End If
        Vorgang.ZahlungsMethode = FirstRow("SELECT Methode FROM `ofAdressen-Zahlungsmethoden` WHERE Standart<>0 and idnr=" & Vorgang.KundNr)
        Vorgang.Zahlungsbedingung = FirstRow("SELECT Methode FROM `ofAdressen-Zahlungsbedingungen` INNER JOIN grZahlungsbedingung ON Bedingung = Nr  WHERE Standart<>0 and IdNr = " & Vorgang.KundNr)
        Vorgang.TransportMethode = FirstRow("SELECT Methode FROM `ofAdressen-Transportmethoden` WHERE Standart<>0 and idnr=" & Vorgang.KundNr)
        Dim lieferAdresse = FirstRow("SELECT id FROM `ofAdressen-Weitere` WHERE Standard<>0 and idnr=" & Vorgang.KundNr)
        If lieferAdresse > 0 Then
            Vorgang.KundNr2 = lieferAdresse
        End If
    End Sub

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="VorgangTyp"></param>
    ''' <param name="Status"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetVorgangStatusColor(VorgangTyp As String, Status As String) As Color
        Try
            Dim DictKey = VorgangTyp & "-" & Status

            If DictionaryVorgangStatusColor.ContainsKey(DictKey) Then
                Return DictionaryVorgangStatusColor(DictKey)
            End If

            Dim cmd = New MySqlCommand("select style from buchVorgaengeStatus where vorgangtyp = @VorgangTyp and Status = @status")
            cmd.Parameters.AddWithValue("VorgangTyp", VorgangTyp)
            cmd.Parameters.AddWithValue("Status", Status)
            Dim colorHMTL = FirstRow(cmd)
            Dim VorgangStatusColor As Color = GetVorgangDefaultStatusColor(Status)
            If Not IsDBNull(colorHMTL) And colorHMTL IsNot Nothing Then
                VorgangStatusColor = ColorTranslator.FromHtml(colorHMTL)
            End If

            DictionaryVorgangStatusColor.Add(DictKey, VorgangStatusColor)
            Return VorgangStatusColor
        Catch ex As Exception
            Return GetVorgangDefaultStatusColor(Status)
        End Try
    End Function

    Private Function GetVorgangDefaultStatusColor(Status As String)
        Select Case Status
            Case VorgangStatus.ABGESCHLOSSEN : Return Color.DarkGray
            Case VorgangStatus.ANGENOMMEN : Return Color.Orange
            Case VorgangStatus.AUSGEDRUCKT : Return Color.DarkGreen
            Case VorgangStatus.KUECHE : Return Color.Green
            Case VorgangStatus.NEU : Return Color.Orange
            Case VorgangStatus.NICHT_ZUGESTELLT : Return Color.Red
            Case VorgangStatus.WIRD_ZUGESTELLT : Return Color.Gray
            Case VorgangStatus.ZUGESTELLT : Return Color.Gray
            Case VorgangStatus.ZUSPAET : Return Color.Pink
        End Select
        Return ColorTranslator.FromHtml("#FFFFFF")
    End Function


    Public Function GetVorgangStatusParam(VorgangTyp As String, Status As String, Feld As String) As String
        Try
            Dim r = FirstRow("select " & Feld & " as Feld from buchVorgaengeStatus where vorgangtyp = '" & VorgangTyp & "' and status = '" & Status & "'")
            If Not IsDBNull(r) Then
                Return r
            End If
        Catch ex As Exception
            'Ignore
        End Try
        Return Nothing
    End Function

    Public Function GetVorgangStatus(VorgangTyp As String,
                                     VorgangNummer As Integer)
        Dim cmdSel As New MySqlCommand("select status from buchVorgang where typ = @VorgangTyp and nummer=@VorgangNummer")
        cmdSel.Parameters.AddWithValue("VorgangTyp", VorgangTyp)
        cmdSel.Parameters.AddWithValue("VorgangNummer", VorgangNummer)
        Return FirstRow(cmdSel)
    End Function
    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="Vorgangtyp"></param>
    ''' <param name="VorgangNummer"></param>
    ''' <param name="Status"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function SetVorgangStatus(VorgangTyp As String,
                                     VorgangNummer As Integer,
                                     Status As String,
                                     MitarbeiterNr As Integer,
                                     silent As Boolean) As Boolean

        'check if such a state exist

        Dim cmd1 = New MySqlCommand("select id from buchVorgaengeStatus where vorgangtyp = @VorgangTyp and Status = @status")
        cmd1.Parameters.AddWithValue("VorgangTyp", VorgangTyp)
        cmd1.Parameters.AddWithValue("Status", Status)
        Dim id = FirstRow(cmd1)
        If Not IsNumeric(id) Then
            DefiniereVorgangAktion(VorgangTyp, Status)
            Return False
        End If

        If Status = VorgangStatus.ZUGESTELLT OrElse Status = VorgangStatus.NICHT_ZUGESTELLT Then
            Dim position As String = MitarbeiterPosition(MitarbeiterNr)
            If position <> "Zusteller" Then
                ShowUserMessage("Zuerst einen Mitarbeiter mit der Position Zusteller auswählen! Aktuelle Position ist " & position & ".", "Zusteller auswählen", vbCritical, silent)
                Return False
            End If
        End If

        If Not silent Then

            Dim cmdCheckFirst As New MySqlCommand("select MitarbeiterNr from `buchVorgang-Status` where VorgangTyp=@VorgangTyp and VorgangNummer=@VorgangNummer and Status=@Status")
            cmdCheckFirst.Parameters.AddWithValue("VorgangTyp", VorgangTyp)
            cmdCheckFirst.Parameters.AddWithValue("VorgangNummer", VorgangNummer)
            cmdCheckFirst.Parameters.AddWithValue("Status", Status)
            Dim oldMitarbeiterNr = FirstRow(cmdCheckFirst)

            If Not IsNothing(oldMitarbeiterNr) And oldMitarbeiterNr > 0 And oldMitarbeiterNr <> MitarbeiterNr Then
                Dim mitarbeiter = MitarbeiterName(oldMitarbeiterNr)
                If Not IsNothing(mitarbeiter) Then
                    Dim msg = String.Format(Messages.ModuleBuchVorgang_uebernehmen, mitarbeiter)
                    If MsgBox(msg, vbYesNo) = vbNo Then
                        Return False
                    End If
                End If
            ElseIf Not IsNothing(oldMitarbeiterNr) And oldMitarbeiterNr > 0 And oldMitarbeiterNr = MitarbeiterNr Then
                Return False
            End If

        End If

        Dim alterStatus = GetVorgangStatus(VorgangTyp, VorgangNummer)
        If Not IsNull(alterStatus) Then
            Dim vorgEig = intrasell.vorgang.GetVorgangEigenschaft(VorgangTyp, VorgangNummer, "Status")
            If vorgEig <> alterStatus Then
                intrasell.vorgang.SetVorgangEigenschaft(VorgangTyp, VorgangNummer, "Status", alterStatus)
            End If
        End If

        Dim cmdUpd As New MySqlCommand("UPDATE buchVorgang SET status = @Status where typ=@VorgangTyp and nummer=@VorgangNummer")
        cmdUpd.Parameters.AddWithValue("Status", Status)
        cmdUpd.Parameters.AddWithValue("VorgangTyp", VorgangTyp)
        cmdUpd.Parameters.AddWithValue("VorgangNummer", VorgangNummer)
        RunSQL(cmdUpd)

        Dim cmdDel As New MySqlCommand("delete from `buchVorgang-Status` where VorgangTyp=@VorgangTyp and VorgangNummer=@VorgangNummer and Status=@Status")
        cmdDel.Parameters.AddWithValue("VorgangTyp", VorgangTyp)
        cmdDel.Parameters.AddWithValue("VorgangNummer", VorgangNummer)
        cmdDel.Parameters.AddWithValue("Status", Status)
        RunSQL(cmdDel)

        Dim cmd As New MySqlCommand("Insert into `buchVorgang-Status` (VorgangTyp, VorgangNummer, Status, MitarbeiterNr, Datum) Values (@VorgangTyp, @VorgangNummer, @Status, @MitarbeiterNr, @Datum)")
        cmd.Parameters.AddWithValue("VorgangTyp", VorgangTyp)
        cmd.Parameters.AddWithValue("VorgangNummer", VorgangNummer)
        cmd.Parameters.AddWithValue("MitarbeiterNr", MitarbeiterNr)
        cmd.Parameters.AddWithValue("Datum", Now)
        cmd.Parameters.AddWithValue("Status", Status)
        RunSQL(cmd)

        Return True
    End Function

    Friend Sub VorgaengeZusammenlegen(offeneBestellung As OffeneBestellung)
        WriteLog($"VorgaengeZusammenlegen für {offeneBestellung.Name}")
        CurrentDB.Close()
        CurrentDB.Open()
        Dim tr = CurrentDB.BeginTransaction()
        Try
            Dim cmd0 As New MySqlCommand("select Typ, Nummer, Summe, SummeMWST, SummeBrutto from buchVorgang where Typ='AU' and abgeschlossen=0 and Nummer != @Nummer  and KundNr=@KundNR order by Datum")
            cmd0.Parameters.AddWithValue("Nummer", offeneBestellung.Nummer)
            cmd0.Parameters.AddWithValue("KundNr", offeneBestellung.IDNR)
            Dim alleAufträge = OpenRecordsetInMemory(cmd0)
            Dim index = 2000
            For Each o In alleAufträge.Rows
                SetAbgeschlossenEinfach(o("Typ"), o("Nummer"))

                Dim cmd As New MySqlCommand("update `buchVorgang-Artikel` set id=id+@index, Nummer=@NeueNummer where Nummer=@AlteNummer and Typ='AU' ")
                cmd.Parameters.AddWithValue("index", index)
                cmd.Parameters.AddWithValue("NeueNummer", offeneBestellung.Nummer)
                cmd.Parameters.AddWithValue("AlteNummer", o("Nummer"))
                RunSQL(cmd)

                Dim cmd2 As New MySqlCommand("update `buchVorgang` set Summe=Summe+@Summe, SummeMWST=SummeMWST+@SummeMWST, SummeBrutto=SummeBrutto+@SummeBrutto where Nummer=@NeueNummer and Typ='AU' ")
                cmd2.Parameters.AddWithValue("NeueNummer", offeneBestellung.Nummer)
                cmd2.Parameters.AddWithValue("Summe", o("Summe"))
                cmd2.Parameters.AddWithValue("SummeMWST", o("SummeMWST"))
                cmd2.Parameters.AddWithValue("SummeBrutto", o("SummeBrutto"))
                RunSQL(cmd2)

                Dim cmd3 As New MySqlCommand("update `buchVorgang` set Summe=0, SummeMWST=0, SummeBrutto=0 where Nummer=@NeueNummer and Typ='AU' ")
                cmd3.Parameters.AddWithValue("NeueNummer", o("Nummer"))
                RunSQL(cmd3)
                index += 1000
            Next
            tr.Commit()
        Catch ex As Exception
            tr.Rollback()
        End Try

    End Sub

    ''' <summary>
    ''' Storniert einen Vorgang.
    ''' Die Nummer wird auch freigegeben und dann wieder verwendet, aber nur wenn das die letzte Nummer ist und Vorgang noch nicht abgeschlossen ist
    ''' </summary>
    ''' <param name="VorgangTyp"></param>
    ''' <param name="VorgangNummer"></param>
    ''' <param name="silent"></param>
    ''' <returns>True wenn storniert wurde</returns>
    ''' <remarks></remarks>
    Public Function VorgangStorno(VorgangTyp As String,
                                  VorgangNummer As String,
                                  Optional silent As Boolean = False,
                                  Optional ByRef stornoVorgangNummer As String = Nothing,
                                  Optional benutzeTransaktion As Boolean = True) As Boolean


        If IsNull(VorgangNummer) Then
            Return False
        End If

        'Prüfung
        Dim wurdeStorniert As String = intrasell.vorgang.GetVorgangEigenschaft(VorgangTyp, VorgangNummer, "STORNO")
        If Not IsNull(wurdeStorniert) AndAlso wurdeStorniert.Contains("STOR") Then
            If Not silent Then
                Dim msg As String = Messages.ModuleBuchVorgang_bereits_storniert & wurdeStorniert
                ShowUserMessage(msg, Messages.ModuleBuchVorgang_bereits_storniert_titel, vbInformation, silent)
            End If
            Return False
        End If

        'Vorgänge älter als XXX Tage nicht erlauben 

        Dim cmd = New MySqlCommand("select Datum from buchVorgang where Typ=@VorgangTyp and Nummer=@VorgangNummer")
        cmd.Parameters.AddWithValue("VorgangTyp", VorgangTyp)
        cmd.Parameters.AddWithValue("VorgangNummer", VorgangNummer)

        Dim VorgangDatum = FirstRow(cmd)
        Dim STORNO_TAGE = VarValue_Default("STORNO_TAGE", "3")
        Dim vNr = VorgangTyp & "-" & VorgangNummer
        If VorgangDatum < Today.AddDays(-1 * STORNO_TAGE) Then

            Dim msg As String = String.Format(Messages.ModuleBuchVorgang_Vorgang_zu_alt, vNr, VorgangDatum, STORNO_TAGE)
            ShowUserMessage(msg, Messages.ModuleBuchVorgang_Vorgang_zu_alt_Titel, vbInformation, silent)
            Return False
        End If

        Dim stornieren As Boolean = silent
        'Prüfung ob bereits storniert 

        If Not silent Then
            Dim msg = String.Format(Messages.ModuleBuchVorgang_Vorgang_stornieren, vNr)
            stornieren = MsgBox(msg, vbYesNo) = vbYes
        End If

        Dim NeueZahlungsMethode = Nothing
        'Prüfung Zahlungsmethode 
        Dim vorgangRow = LadeVorgangRow(VorgangTyp, VorgangNummer)
        If VorgangTyp = VorgangTypen.AR AndAlso vorgangRow.Bezahlt Then
            If Not silent AndAlso vorgangRow.ZahlungsMethode <> "Bar" Then
                'TODO Umbauen - es ist nicht gut wenn mitten in Transaktionen MsgBoxes auftauchen
                Dim msg = String.Format(Messages.ModuleBuchVorgang_Vorgang_Betrag_ausbezahlt, vorgangRow.SummeBrutto, vorgangRow.ZahlungsMethode)
                If MsgBox(msg, vbYesNo) = vbYes Then
                    NeueZahlungsMethode = "Bar"
                End If
            End If
        End If


        If stornieren Then
            Application.UseWaitCursor = True

            Dim tr As MySqlTransaction = Nothing
            If benutzeTransaktion Then
                CurrentDB.Close()
                CurrentDB.Open()
                tr = CurrentDB.BeginTransaction()
            End If

            Try
                Dim lagerMsg As String = ""
                Dim Abgeschlossen, Bezahlt As Boolean
                Dim Wohin As Object
                Dim KundNr As Integer
                Dim ZahlungsMethode As String = Nothing
                Dim BetragBrutto As Decimal

                Try
                    cmd = New MySqlCommand("select Abgeschlossen, Bezahlt, KundNr, Wohin, ZahlungsMethode, SummeBrutto from buchVorgang " &
                         " where Typ= @VorgangTyp and nummer = @VorgangNummer")
                    cmd.Parameters.AddWithValue("VorgangTyp", VorgangTyp)
                    cmd.Parameters.AddWithValue("VorgangNummer", VorgangNummer)

                    Dim rsTable = OpenRecordsetInMemory(cmd)

                    If rsTable.Rows.Count > 0 Then
                        Dim rs = rsTable.Rows(0)
                        Abgeschlossen = rs("abgeschlossen")
                        Bezahlt = rs("Bezahlt")
                        KundNr = rs("KundNr")
                        Wohin = rs("Wohin")
                        Try
                            BetragBrutto = rs("SummeBrutto")
                        Catch ex As Exception
                            HandleAppError(ex, "SummeBrutto lesen", Silent:=True)
                        End Try

                        Try
                            If Not IsDBNull(rs("ZahlungsMethode")) Then
                                ZahlungsMethode = rs("ZahlungsMethode")
                            End If

                        Catch ex As Exception
                            HandleAppError(ex, "ZahlungsMethode lesen", Silent:=True)
                        End Try
                    Else
                        Dim msgex = String.Format(Messages.ModuleBuchVorgang_Vorgang_fehlt, VorgangTyp & "-" & VorgangNummer)
                        Throw New Exception(msgex)
                    End If

                Catch ex As Exception
                    HandleAppError(ex, "Vorgang für Storno lesen", Silent:=True)
                    Throw ex
                End Try

                If Abgeschlossen <> 0 Then 'abgeschlossen  
                    stornoVorgangNummer = VorgangKonvertieren(VorgangTyp, VorgangTyp, VorgangNummer, KundNr, True, False, True)

                    Dim laggerBuchungCmd = New IntraSellLagerbuchungCommand() With {.Typ = VorgangTyp, .Nummer = stornoVorgangNummer}
                    ModuleGlobal.RequestCommandDirekt(laggerBuchungCmd)
                    'LagerBuchungVorgangBeimAbschliessen(VorgangTyp, stornoVorgangNummer)

                    If VorgangTyp = VorgangTypen.AR AndAlso Bezahlt Then
                        If silent Then
                            ZahlungsMethode = "Bar"
                        Else
                            If ZahlungsMethode <> "Bar" AndAlso NeueZahlungsMethode IsNot Nothing Then
                                ZahlungsMethode = NeueZahlungsMethode
                            End If
                        End If

                        MakeKassaBuchEintrag(Now(), VorgangTyp, VorgangTyp & "-" & stornoVorgangNummer, -1 * GetSummeVorgang(VorgangTyp, VorgangNummer),
                                                  MitarbeiterID, ZahlungsMethode, VorgangTyp, stornoVorgangNummer)
                    End If
                    SetAbgeschlossen(VorgangTyp, stornoVorgangNummer)
                    intrasell.vorgang.AddVorgangEigenschaft(VorgangTyp, VorgangNummer, "STORNO", "STORNIERT mit " & stornoVorgangNummer)
                    intrasell.vorgang.AddVorgangEigenschaft(VorgangTyp, stornoVorgangNummer, "STORNO", "STORNO von " & VorgangNummer)
                    SetVorgangStatus(VorgangTyp, stornoVorgangNummer, VorgangStatus.STORNIERT, MitarbeiterID, silent)
                Else
                    'delete Eigenschaften
                    Dim sql As String = "delete from [buchvorgaengeeigenschaften] where VorgangTyp='" & VorgangTyp & "' and Nummer =" & VorgangNummer
                    RunSQL(sql)
                    'delete Positionen
                    sql = "delete from `buchVorgang-Artikel` where Typ='" & VorgangTyp & "' and  Nummer =" & VorgangNummer
                    RunSQL(sql)
                    'delete Vorgang
                    sql = "delete from buchVorgang where Typ='" & VorgangTyp & "' and  Nummer =" & VorgangNummer
                    RunSQL(sql)

                End If

                If benutzeTransaktion Then tr.Commit()

                Dim msg = String.Format(Messages.ModuleBuchVorgang_Vorgang_storniert, VorgangTyp, VorgangNummer) & " " & lagerMsg
                ShowUserMessage(msg, "Storniert", MsgBoxStyle.Information, silent)
                Return True
            Catch ex As Exception
                WriteLog("ERROR in storno " & ex.Message)
                If benutzeTransaktion Then tr.Rollback()

                Dim msg = "Die Transaktion wurde abgebrochen! Details:" & ex.Message
                ShowUserMessage(msg, "Abbruch", MsgBoxStyle.Critical, silent)
                Return False
            Finally
                Application.UseWaitCursor = False
            End Try
        End If

    End Function

    Friend Sub ReloadSetting()
        localeSettings = New ClassSettings
    End Sub

    Sub PruefeVorgang(VorgangInBearbeitung As VorgangInBearbeitung)
        PruefeVorgangSummen(VorgangInBearbeitung)
        PruefeVorgangMWST(VorgangInBearbeitung)
    End Sub

    ''' <summary>
    ''' Exception falls die Summen mit den Positionen nicht übereinstimmen
    ''' </summary>
    ''' <param name="VorgangInBearbeitung"></param> 
    ''' <remarks></remarks>
    Sub PruefeVorgangSummen(VorgangInBearbeitung As VorgangInBearbeitung)
        Dim sql As String = "select round(v.Summe,2) as SummeN, round(v.SummeBrutto,2) summeB, round(sum((va.stk*.va.Preis_Netto)),2) as summeVAN, round(sum((va.stk*.va.Preis_Brutto)),2) as summeVAB  " &
        " FROM buchvorgang v, `buchvorgang-artikel` va" &
        " WHERE v.Nummer = va.Nummer And v.typ = va.typ" &
        " and v.Nummer = @VorgangNummer And v.typ = @VorgangTyp " &
        " GROUP BY v.Nummer, v.typ" &
        " HAVING abs(summeB - summeVAB) > 0.01  Or abs(summeN - summeVAN) > 0.01"
        Dim cmd = New MySqlCommand(sql)
        cmd.Parameters.AddWithValue("VorgangNummer", VorgangInBearbeitung.Nummer)
        cmd.Parameters.AddWithValue("VorgangTyp", VorgangInBearbeitung.Typ)

        Dim summeRow = OpenRecordsetInMemory(cmd)
        WriteDebug("SQL: " & sql)
        If summeRow.Rows.Count > 0 Then
            Dim summeBruttoPositionen = summeRow.Rows(0)("summeVAB")
            Dim summeBrutto = summeRow.Rows(0)("summeB")
            Dim differenz = summeBrutto - summeBruttoPositionen
            If Math.Abs(differenz) > 0 Then
                Dim msg As String = String.Format(Messages.ModuleBuchVorgang_Vorgang_Summe_inkorrekt, VorgangInBearbeitung.Typ, VorgangInBearbeitung.Nummer, summeBrutto, summeBruttoPositionen, differenz)
                WriteLog("Prüf SQL " & sql)
                WriteLog("Throw exception: " & msg)
                Throw New Exception(msg)
            End If
        End If
    End Sub

    ''' <summary>
    ''' Exception falls die MWST nicht stimmt
    ''' </summary>
    ''' <param name="VorgangInBearbeitung"></param>
    ''' <remarks></remarks>
    Public Sub PruefeVorgangMWST(VorgangInBearbeitung As VorgangInBearbeitung)
        'MWST ist 0
        Dim sql = "SELECT v.SummeMWST, v.SummeBrutto, kg.RechungenMitMWST, a.Kundengruppe FROM buchvorgang v, `ofadressen-settings` a, `ofadressen-kundengruppen` kg" &
                   " WHERE v.KundNr = a.IDNR And a.Kundengruppe = kg.Gruppe and Nummer=@Nummer and Typ=@Typ"
        Dim cmd As New MySqlCommand(sql)
        cmd.Parameters.AddWithValue("Nummer", VorgangInBearbeitung.Nummer)
        cmd.Parameters.AddWithValue("Typ", VorgangInBearbeitung.Typ)

        Dim rs = OpenRecordsetInMemory(cmd)
        If rs.Rows.Count > 0 Then
            Dim r = rs.Rows(0)
            Dim mwst = CDec(r("SummeMWST"))
            Dim kundengruppe = r("Kundengruppe")
            Dim RechungenMitMWST = CBool(r("RechungenMitMWST"))
            If mwst <> 0 AndAlso Not RechungenMitMWST Then
                Dim msg = String.Format(Messages.ModuleBuchVorgang_Vorgang_MWST_inkorrekt1, VorgangInBearbeitung.Typ, VorgangInBearbeitung.Nummer, kundengruppe)
                Throw New Exception(msg)
            End If

            ''Deaktiviert am 01.10.2024 weil Steuer wie z.Bsp. Kurtaxe keine Steuer haben darf
            ''If mwst = 0 AndAlso RechungenMitMWST AndAlso brutto <> 0 Then
            ''    Dim msg = String.Format(Messages.ModuleBuchVorgang_Vorgang_MWST_inkorrekt2, VorgangInBearbeitung.Typ, VorgangInBearbeitung.Nummer, kundengruppe)
            ''    Throw New Exception(msg)
            ''End If
        End If
    End Sub

    Public Function OpenVorgangFunctionByWoher(Woher As String, Optional neuesFenster As Boolean = True) As Vorgang
        Dim typ = Woher.Substring(0, 2)
        Dim nummer = Woher.Replace(typ, "")
        If IstVorgangTyp(typ) And IsNumeric(nummer) Then
            Return OeffneVorgangByNummer(typ, nummer, True)
        End If
        Return Nothing
    End Function

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="VorgangTyp"></param>
    ''' <param name="VorgangNummer"></param>
    ''' <param name="KundNr"></param>
    ''' <remarks></remarks>
    Public Sub SetStandartBedingung(VorgangTyp As String, VorgangNummer As Integer, KundNr As String)
        Dim zb, zm, tm
        zb = TableValue("grZahlungsbedingung", "Nr", TableValue("[ofAdressen-Zahlungsbedingungen]", "Idnr", KundNr, "Bedingung"), "Methode")
        zm = TableValue("[ofAdressen-ZahlungsMethoden]", "Idnr", KundNr, "Methode")
        tm = TableValue("[ofAdressen-TransportMethoden]", "Idnr", KundNr, "Methode")

        If InStr(zb, "vorhanden") > 0 Then zb = ""
        If InStr(zm, "vorhanden") > 0 Then zm = ""
        If InStr(tm, "vorhanden") > 0 Then tm = ""

        Dim sql As String
        sql = "Update buchVorgang " &
            " set ZahlungsBedingung=@ZahlungsBedingung, Zahlungsmethode= @Zahlungsmethode, TransportMethode=@TransportMethode " &
            " where Nummer=@VorgangNummer and Typ=@VorgangTyp"

        Dim cmd = New MySqlCommand(sql)
        cmd.Parameters.AddWithValue("ZahlungsBedingung", zb)
        cmd.Parameters.AddWithValue("Zahlungsmethode", zm)
        cmd.Parameters.AddWithValue("TransportMethode", tm)
        cmd.Parameters.AddWithValue("Vorgangtyp", VorgangTyp)
        cmd.Parameters.AddWithValue("VorgangNummer", VorgangNummer)
        RunSQL(cmd)
    End Sub


    Public Sub SetZahlungsmethode(VorgangTyp As String, VorgangNummer As Integer, zahlungsmethode As String)

        Dim sql As String
        sql = "Update buchVorgang " &
            " set Zahlungsmethode= @Zahlungsmethode " &
            " where Nummer=@VorgangNummer and Typ=@VorgangTyp"

        Dim cmd = New MySqlCommand(sql)
        cmd.Parameters.AddWithValue("Zahlungsmethode", zahlungsmethode)
        cmd.Parameters.AddWithValue("Vorgangtyp", VorgangTyp)
        cmd.Parameters.AddWithValue("VorgangNummer", VorgangNummer)
        RunSQL(cmd)
    End Sub

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="Vorgang"></param>
    ''' <param name="ZielVorgangTyp"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function KonvertiereVorgang(Vorgang As VorgangInBearbeitung, ZielVorgangTyp As String) As VorgangInBearbeitung
        WriteLog("KonvertiereVorgang " & Vorgang.ToString)

        Dim tr As MySqlTransaction = Nothing
        Try

            Application.UseWaitCursor = True

            CurrentDB.Close()
            CurrentDB.Open()
            tr = CurrentDB.BeginTransaction
            'abschliessen
            Dim AbgeschlossenOk = VorgangAbschliessen(Vorgang.Typ, Vorgang.Nummer, True, benutzeTransaktion:=False)
            If Not AbgeschlossenOk Then
                tr.Rollback()
                Return Nothing
            End If
            Dim NewNummer As String = intrasell.vorgang.ConvertFromTo(Vorgang.Typ,
                                                        ZielVorgangTyp,
                                                        Vorgang.Nummer,
                                                        NewKundNr:=Vorgang.KundNr,
                                                        silent:=False,
                                                        benutzeTransaktion:=False,
                                                        isStorno:=False)
            Dim NewVorgang = New VorgangInBearbeitung(ZielVorgangTyp, NewNummer, Vorgang.KundNr, Nothing)
            If Vorgang.GegebenBar > 0 Then
                intrasell.vorgang.AddVorgangEigenschaft(ZielVorgangTyp, NewNummer, BARGELD_GEGEBEN, Vorgang.GegebenBar)
            End If

            If Vorgang.Resto > 0 Then
                intrasell.vorgang.AddVorgangEigenschaft(ZielVorgangTyp, NewNummer, BARGELD_RESTO, Vorgang.Resto)
            End If

            SetVorgangStatus(ZielVorgangTyp, NewNummer, VorgangStatus.NEU, MitarbeiterID, silent:=False)
            SetMitarbeiter(ZielVorgangTyp, NewNummer, MitarbeiterID)
            tr.Commit()
            Return NewVorgang
        Catch ex As Exception
            If tr IsNot Nothing Then
                tr.Rollback()
            End If
            HandleAppError(ex)
            Return Nothing
        Finally
            Application.UseWaitCursor = False
        End Try
    End Function

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="Vorgang"></param>
    ''' <param name="ZielVorgangTyp"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function VorgangParken(Vorgang As VorgangInBearbeitung, ZielVorgangTyp As String) As Integer
        Dim tr As MySqlTransaction = Nothing
        Try
            If Vorgang Is Nothing Then
                Return Nothing
            End If
            If IstVorgangAbgeschlossen(Vorgang.Typ, Vorgang.Nummer) Then
                Dim msg = String.Format(Messages.ModuleBuchVorgang_Vorgang_bereits_abgeschlossen, Vorgang.Typ & "-" & Vorgang.Nummer)
                MsgBox(msg, vbCritical, Messages.ModuleBuchVorgang_Vorgang_bereits_abgeschlossen_Titel)
                Return Nothing
            End If

            CurrentDB.Close()
            CurrentDB.Open()
            tr = CurrentDB.BeginTransaction
            Dim kundnr = Vorgang.KundNr
            If kundnr <= 1 Then
                kundnr = ImportKunden.ImportKunden(ExtSystem:="IntraSell", ExternalId:="Geparkt",
                                                   Nachname:="Geparkt", Vorname:="", Firma:="",
                                                   Adresse:="", Land:=43, PLZ:="", Ort:="",
                                                   Tel:="", Mobil:="", Email:="", UID:="", Kundengruppe:="", Preisliste:="")
            End If
            Dim NewNummer As Integer = intrasell.vorgang.ConvertFromTo(Vorgang.Typ,
                                                        ZielVorgangTyp,
                                                        Vorgang.Nummer,
                                                        kundnr,
                                                        False,
                                                        benutzeTransaktion:=False,
                                                        isStorno:=False)

            SetVorgangStatus(ZielVorgangTyp, NewNummer, VorgangStatus.GEPARKT, MitarbeiterID, silent:=False)

            Dim stornoNummer As String = Nothing
            VorgangStorno(Vorgang.Typ, Vorgang.Nummer, silent:=True, stornoVorgangNummer:=stornoNummer, benutzeTransaktion:=False)

            tr.Commit()
            Return NewNummer
        Catch ex As Exception
            If tr IsNot Nothing Then
                tr.Rollback()
            End If
            HandleAppError(ex)
            Return Nothing
        End Try
    End Function

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="Typ"></param>
    ''' <param name="Nummer"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function IstVorgangAbgeschlossen(Typ As String, Nummer As Integer) As Boolean
        Dim cmd As New MySqlCommand("select abgeschlossen from buchVorgang where Typ=@Typ and Nummer=@Nummer")
        cmd.Parameters.AddWithValue("Typ", Typ)
        cmd.Parameters.AddWithValue("Nummer", Nummer)
        Dim result = FirstRow(cmd)
        If TypeOf (result) Is String AndAlso result = NOT_AVAILABLE Then
            Return False
        End If

        Return result
    End Function

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="Typ"></param>
    ''' <param name="Nummer"></param>
    ''' <param name="silent"></param>
    ''' <returns>Returns True if Operation Successfull, else False</returns>
    ''' <remarks> </remarks>
    Public Function VorgangAbschliessen(Typ As String, Nummer As String,
                                        Optional silent As Boolean = False,
                                        Optional benutzeTransaktion As Boolean = True) As Boolean
        Try
            PruefeVorgang(New VorgangInBearbeitung(Typ, Nummer))
        Catch ex As Exception
            MsgBox(ex.Message, MsgBoxStyle.Critical, "Fehler bei der Summenprüfung")
            Return False
        End Try

        Application.UseWaitCursor = True
        Dim tr As MySqlTransaction = Nothing
        If benutzeTransaktion Then
            CurrentDB.Close()
            CurrentDB.Open()
            tr = CurrentDB.BeginTransaction()
        End If

        Try

            Dim Abgeschlossen As Boolean = IstVorgangAbgeschlossen(Typ, Nummer)

            If IsNull(Abgeschlossen) OrElse Abgeschlossen = 0 Then
                Dim laggerBuchungCmd = New IntraSellLagerbuchungCommand() With {.Typ = Typ, .Nummer = Nummer}
                ModuleGlobal.RequestCommandDirekt(laggerBuchungCmd)
                ' Dim lagerMsg = LagerBuchungVorgangBeimAbschliessen(Typ, Nummer)

                'MitarbeiterNr 
                'ARFAIAN: Mitarbeiter nicht setzen wenn von einem anderen bereits erstellt
                SetMitarbeiter(Typ, Nummer, MitarbeiterID)
                SetVorgangStatus(Typ, Nummer, VorgangStatus.ABGESCHLOSSEN, MitarbeiterID, silent)
                SetAbgeschlossen(Typ, Nummer)
                SetBezahltLautKassenbuchungen(Typ, Nummer)

                If benutzeTransaktion Then tr.Commit()

                Dim msg = String.Format(Messages.ModuleBuchVorgang_Vorgang_abgeschlossen, Typ, Nummer)
                ShowUserMessage(msg, Messages.ModuleBuchVorgang_Vorgang_abgeschlossen_Titel, MsgBoxStyle.Information, silent)
            Else
                Dim msg = String.Format(Messages.ModuleBuchVorgang_Vorgang_bereits_abgeschlossen, Typ & "-" & Nummer)
                ShowUserMessage(msg, Messages.ModuleBuchVorgang_Vorgang_abgeschlossen_Titel, MsgBoxStyle.Exclamation, silent)
            End If

            Return True
        Catch ex As Exception
            HandleAppError(ex, Silent:=True)
            If benutzeTransaktion Then tr.Rollback()
            HandleAppError(ex)
            Return False
        Finally
            Application.UseWaitCursor = False
        End Try
    End Function


    ''' <summary>
    ''' Vorgang abschliessen
    ''' </summary>
    ''' <param name="Vorgang"></param>
    ''' <param name="silent"></param>
    ''' <param name="pruefeGegebenBar"></param>
    ''' <remarks></remarks>
    Private Sub VorgangAbschliessenBar(Vorgang As dsVorgaenge.buchvorgangRow, silent As Boolean, pruefeGegebenBar As Boolean)

        Cursor.Current = Cursors.WaitCursor
        If Vorgang Is Nothing Then
            Dim msg = String.Format(Messages.ModuleBuchVorgang_Vorgang_fehlt, "") '"Der Vorgang konnte nicht gefunden werden!"
            WriteLog(msg)
            ShowUserMessage(msg, "VorgangAbschliessenBar Vorgang eventuell storniert", vbCritical, silent)
            Cursor.Current = Cursors.Default
            Return
        End If

        'Prüfe ob die Bezahlmethode gesetzt ist 
        Dim zahlMethodeNichtGesetzt = False
        If Vorgang.IsZahlungsMethodeNull Then
            zahlMethodeNichtGesetzt = True
        Else
            If Vorgang.ZahlungsMethode = "" Then
                zahlMethodeNichtGesetzt = True
            End If
        End If

        If zahlMethodeNichtGesetzt Then
            Dim msg = String.Format(Messages.ModuleBuchVorgang_Zahlungsmethode_fehlt, Vorgang.Typ, Vorgang.Nummer)
            ShowUserMessage(msg, Messages.ModuleBuchVorgang_Zahlungsmethode_fehlt, vbCritical, silent)
            Cursor.Current = Cursors.Default
            Return
        End If

        'Prüfe in der Tabelle ob abgeschlossen 
        Dim abgeschlossenAm = intrasell.vorgang.GetVorgangEigenschaft(Vorgang.Typ, Vorgang.Nummer, "AbgeschlossenAm")
        Dim istNichtAbgeschlossen As Boolean = abgeschlossenAm Is Nothing
        If Not istNichtAbgeschlossen Then
            Dim msg = String.Format(Messages.ModuleBuchVorgang_Vorgang_bereits_abgeschlossen_am, Vorgang.Typ & "-" & Vorgang.Nummer, abgeschlossenAm)
            ShowUserMessage(msg, Messages.ModuleBuchVorgang_Vorgang_bereits_abgeschlossen_Titel, vbCritical, silent)
            Cursor.Current = Cursors.Default
            Return
        End If

        Try
            SetSummeVorgang(Vorgang.Typ, Vorgang.Nummer)
            PruefeVorgang(New VorgangInBearbeitung(Vorgang.Typ, Vorgang.Nummer))
        Catch ex As Exception
            ShowUserMessage(ex.Message, "Fehler", vbCritical, silent)
            Cursor.Current = Cursors.Default
            Return
        End Try

        If pruefeGegebenBar Then
            If Vorgang.IsGegebenBarNull Then
                Dim msg = Messages.TouchErfassung_GegebenBar_fehlt
                ShowUserMessage(msg, "Bar erfasst?", vbCritical, silent)
                Cursor.Current = Cursors.Default
                Return
            End If
        Else
            Vorgang.GegebenBar = 0
        End If

        If Not Vorgang.Abgeschlossen Then
            CurrentDB.Close()
            CurrentDB.Open()
            Dim tr As MySqlTransaction = CurrentDB.BeginTransaction()
            Dim lagerMsg = ""
            Try
                SetGegebenBar(Vorgang)

                Vorgang.Datum = Now 'Zeitstempel aktualisieren 
                intrasell.vorgang.SetVorgangDatum(Vorgang.Typ, Vorgang.Nummer, Now)
                intrasell.vorgang.SetVorgangEigenschaft(Vorgang.Typ, Vorgang.Nummer, "StartErfassung", Vorgang.Datum)
                intrasell.vorgang.SetVorgangEigenschaft(Vorgang.Typ, Vorgang.Nummer, "AbgeschlossenAm", Now)

                'If Vorgang.IsMitarbeiterNrNull Then 
                'Mitarbeiter der Boniert wird als Mitarbieter der KAssiert ausgewiesen
                Vorgang.MitarbeiterNr = MitarbeiterID
                SetMitarbeiter(Vorgang.Typ, Vorgang.Nummer, MitarbeiterID)
                'End If
                Dim laggerBuchungCmd = New IntraSellLagerbuchungCommand() With {.Typ = Vorgang.Typ, .Nummer = Vorgang.Nummer}
                ModuleGlobal.RequestCommandDirekt(laggerBuchungCmd)
                'lagerMsg = LagerBuchungVorgangBeimAbschliessen(Vorgang.Typ, Vorgang.Nummer)

                SetVorgangStatus(Vorgang.Typ, Vorgang.Nummer, VorgangStatus.ABGESCHLOSSEN, MitarbeiterID, silent)
                SetAbgeschlossen(Vorgang.Typ, Vorgang.Nummer)
                Vorgang.Abgeschlossen = True

                MakeKassaBuchEintrag(Now(), Vorgang.Typ, Vorgang.Typ & "-" & Vorgang.Nummer, Vorgang.SummeBrutto, Vorgang.MitarbeiterNr, Vorgang.ZahlungsMethode,
                                          Vorgang.Typ, Vorgang.Nummer)
                SetBezahlt(Vorgang.Typ, Vorgang.Nummer)
                Vorgang.Bezahlt = True

                VorgangDrucken(Vorgang.Typ, Vorgang.Nummer, isUeberleitung:=True, showPreview:=VarValue_Default(PRINT_AM_BILDSCHIRM, False))
                Vorgang.Ausgedruckt = True

                tr.Commit()
            Catch ex As Exception
                If tr IsNot Nothing Then tr.Rollback()
                Cursor.Current = Cursors.Default
                HandleAppError(ex, "VorgangAbschliessenBar")
                Return
            Finally
                Cursor.Current = Cursors.Default
            End Try

            Dim msg = String.Format(Messages.ModuleBuchVorgang_Vorgang_abgeschlossen, Vorgang.Typ, Vorgang.Nummer) & " " & lagerMsg
            ShowUserMessage(msg, Messages.ModuleBuchVorgang_Vorgang_abgeschlossen_Titel, MsgBoxStyle.Information, silent)

            Try
                RaiseEvent VorgangAbgeschlossen(Vorgang.SummeBrutto)
            Catch ex As Exception
                HandleAppError(ex, "RaiseEvent VorgangAbgeschlossen", Silent:=True)
            End Try

        Else
            Dim msg = String.Format(Messages.ModuleBuchVorgang_Vorgang_bereits_abgeschlossen, Vorgang.Typ & "-" & Vorgang.Nummer)
            ShowUserMessage(msg, Messages.ModuleBuchVorgang_Vorgang_bereits_abgeschlossen_Titel, vbCritical, silent)
        End If
        Cursor.Current = Cursors.Default
    End Sub

    ''' <summary>
    ''' Gegeben Bar als Eigenschaften setzen 
    ''' </summary>
    ''' <param name="Vorgang"></param>
    ''' <remarks></remarks>
    Public Sub SetGegebenBar(Vorgang As dsVorgaenge.buchvorgangRow)
        If Not Vorgang.IsGegebenBarNull AndAlso Vorgang.GegebenBar > 0 Then
            intrasell.vorgang.SetVorgangEigenschaft(Vorgang.Typ, Vorgang.Nummer, BARGELD_GEGEBEN, Vorgang.GegebenBar)
            Dim resto As Decimal = Math.Round(Vorgang.GegebenBar - Vorgang.SummeBrutto, 2)
            intrasell.vorgang.SetVorgangEigenschaft(Vorgang.Typ, Vorgang.Nummer, BARGELD_RESTO, resto)
        End If
    End Sub

    Public Function VorgangEntsperren(Typ As String, Nummer As String,
                                    Optional silent As Boolean = False,
                                    Optional benutzeTransaktion As Boolean = True) As Boolean
        Try
            Dim Abgeschlossen As Boolean = IstVorgangAbgeschlossen(Typ, Nummer)
            If Abgeschlossen Then
                SetNichtAbgeschlossen(Typ, Nummer)
                Return True
            Else
                If Not silent Then
                    Dim msg = String.Format(Messages.ModuleBuchVorgang_Vorgang_nicht_abgeschlossen, Typ, Nummer)
                    MsgBox(msg, vbCritical)
                End If
                Return False
            End If
        Catch ex As Exception
            HandleAppError(ex)
        End Try
        Return False
    End Function

    Public Function VorgangSperren(Typ As String, Nummer As String,
                                Optional silent As Boolean = False,
                                Optional benutzeTransaktion As Boolean = True) As Boolean
        Try
            Dim Abgeschlossen As Boolean = IstVorgangAbgeschlossen(Typ, Nummer)
            If Not Abgeschlossen Then
                SetAbgeschlossen(Typ, Nummer)
                Return True
            Else
                If Not silent Then
                    Dim msg = String.Format(Messages.ModuleBuchVorgang_Vorgang_bereits_abgeschlossen, Typ & "-" & Nummer)
                    MsgBox(msg, vbCritical)
                End If
                Return False
            End If
        Catch ex As Exception
            HandleAppError(ex)
        End Try
        Return False
    End Function

    Public Sub ShowUserMessage(Msg As String, Title As String, Style As MsgBoxStyle, Silent As Boolean)
        If Not Silent Then
            ' MsgBox(Msg, Style, Title)
            ModuleMessages.UserMessagePopUp(Title, Msg, Style)
        Else
            RaiseEvent_PostMsgEvent(Msg, Style)
        End If
    End Sub

    Public Sub RaiseEvent_PostMsgEvent(msg As String, Style As MsgBoxStyle)
        If msg <> "" Then
            RaiseEvent PostMsgEvent(msg, Style)
        End If
    End Sub

    ''' <summary>
    ''' Vorgang wird nicht direkt ausgedruckt sondern eingerieht und wird von der Signatur Programm signiert und ausgedruckt. 
    ''' </summary>
    ''' <param name="Typ"></param>
    ''' <param name="Nummer"></param>
    ''' <remarks></remarks>
    Public Sub VorgangAbschliessenEinreihen(Typ As String, Nummer As String, silent As Boolean, pruefeGegebenBar As Boolean)

        Dim PcHatSignaturEinheit = localeSettings.ReadBoolean(Variablen.PcHatSignaturEinheit, True)
        'TODO Nur am PC mit Signatureinheit möglich korrekt
        If PcHatSignaturEinheit Then
            Dim vorgangInBearbeitung = LadeVorgang(Typ, Nummer)
            Dim ZielVorgangTyp = VorgangTypen.AR
            Dim NewNummer = Nummer
            If Typ <> VorgangTypen.AR Then
                NewNummer = KonvertiereVorgang(vorgangInBearbeitung, ZielVorgangTyp).Nummer
            End If
            Dim vorgang = LadeVorgangRow(ZielVorgangTyp, NewNummer)
            If vorgang IsNot Nothing Then
                VorgangAbschliessenBar(vorgang, silent:=silent, pruefeGegebenBar:=pruefeGegebenBar)
            End If
        Else
            intrasell.vorgang.SetVorgangEigenschaft(Typ, Nummer, "PRINT_AM_HOST", Net.Dns.GetHostName)
            AddTask(ModuleTasks.VorgangAbschliessenBar, Typ & "-" & Nummer)

            Dim warteAufSignierungDruckVorgang As VorgangInBearbeitung = LadeVorgang(Typ, Nummer)
            Dim warteAufSignierungDruck = New Thread(AddressOf WarteAufSignierungDruckTask)
            warteAufSignierungDruck.Start(warteAufSignierungDruckVorgang)
        End If

    End Sub

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="FromOrder"></param>
    ''' <param name="ToOrder"></param>
    ''' <param name="FromNummer"></param>
    ''' <param name="NewKundNr"></param>
    ''' <param name="silent"></param>
    ''' <param name="benutzeTransaktion"></param>
    ''' <param name="isStorno"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function VorgangKonvertieren(FromOrder As String,
                                        ToOrder As String,
                                        FromNummer As Integer,
                                        NewKundNr As Integer,
                                        Optional silent As Boolean = False,
                                        Optional benutzeTransaktion As Boolean = True,
                                        Optional isStorno As Boolean = False) As String
        Try
            Return intrasell.vorgang.ConvertFromTo(FromOrder, ToOrder, FromNummer, NewKundNr, silent, benutzeTransaktion, isStorno)
        Catch ex As Exception
            HandleAppError(ex)
            Return Nothing
        End Try
    End Function

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="Typ"></param>
    ''' <param name="Nummer"></param>
    ''' <param name="Betrag"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function KassaBuchung(Typ As String, Nummer As String, Betrag As Decimal) As Boolean
        Dim tr As MySqlTransaction = Nothing
        Try
            Dim cmd = New MySqlCommand("Select bezahlt from buchVorgang where Typ=@Typ and Nummer=@Nummer")
            cmd.Parameters.AddWithValue("Typ", Typ)
            cmd.Parameters.AddWithValue("Nummer", Nummer)
            Dim Bezahlt As Boolean = FirstRow(cmd)

            If Typ = VorgangTypen.AR AndAlso Not Bezahlt Then
                Dim msg = String.Format(Messages.ModuleBuchVorgang_Betrag_eingehoben, Betrag)
                If MsgBox(msg, vbYesNo) = vbYes Then
                    CurrentDB.Close()
                    CurrentDB.Open()
                    tr = CurrentDB.BeginTransaction
                    SetBezahlt(Typ, Nummer)
                    'kassabuch
                    MakeKassaBuchEintrag(Now(), Typ, Typ & "-" & Nummer, Betrag, MitarbeiterID, "Bar", Typ, Nummer)
                    tr.Commit()
                    Return True
                End If

            Else
                If Typ <> VorgangTypen.AR Then
                    Dim msg = String.Format(Messages.ModuleBuchVorgang_Funktion_nur_AR, "KassaBuchung")
                    MsgBox(msg, vbInformation)
                End If
                Return False
            End If

        Catch ex As Exception
            If tr IsNot Nothing Then tr.Rollback()
            HandleAppError(ex)
            Return False
        End Try

        Return True
    End Function

    ''' <summary>
    ''' Vorgang als Ausschuss markieren und abschliessen
    ''' </summary>
    ''' <param name="typ"></param>
    ''' <param name="nummer"></param>
    ''' <param name="grund"></param>
    ''' <remarks></remarks>
    Sub VorgangAusschussBuchung(Typ As String, Nummer As Integer, Grund As String)
        Dim Abgeschlossen As Boolean = IstVorgangAbgeschlossen(Typ, Nummer)
        If Abgeschlossen Then
            Dim msg = String.Format(Messages.ModuleBuchVorgang_Vorgang_bereits_abgeschlossen, Typ & "-" & Nummer)
            MsgBox(msg)
            Return
        End If
        CurrentDB.Close()
        CurrentDB.Open()
        Dim tr As MySqlTransaction = CurrentDB.BeginTransaction()
        Try

            'Kunde für Auswertungen anlegen 
            Dim KundNR = ImportKunden.ImportKunden("IntraSell", Grund, Nachname:=Grund, Vorname:="", Adresse:="", Email:="", Firma:="Ausschuss",
                                                         Kundengruppe:="Ausschuss", Land:=43, Mobil:="", Ort:="", PLZ:="", Preisliste:="", Tel:="", UID:="")


            Dim cmd As New MySqlCommand("update `buchVorgang-Artikel` set Preis_Netto=0, Preis_Brutto=0, MWST=0  " &
                                                       " where Typ=@Typ and Nummer=@nummer ") With {
                .Connection = CurrentDB
                                                       }
            cmd.Parameters.AddWithValue("Typ", Typ)
            cmd.Parameters.AddWithValue("Nummer", Nummer)
            cmd.ExecuteNonQuery()

            cmd = New MySqlCommand("update `buchVorgang` set KundNr=@IDNR,  Notiz=@Notiz " &
                                                      " where Typ=@Typ and Nummer=@nummer ") With {
                .Connection = CurrentDB
                                                      }
            cmd.Parameters.AddWithValue("IDNR", KundNR)
            cmd.Parameters.AddWithValue("Notiz", Grund)
            cmd.Parameters.AddWithValue("Typ", Typ)
            cmd.Parameters.AddWithValue("Nummer", Nummer)
            cmd.ExecuteNonQuery()

            SetSummeVorgang(Typ, Nummer)
            VorgangAbschliessen(Typ, Nummer, True, False)
            tr.Commit()
        Catch ex As Exception
            MsgBox(ex.Message)
            tr.Rollback()
        End Try
    End Sub

    ''' <summary>
    ''' Falls Vorgang über Telefonisch Bestellung kommt hat noch kein Status und es werden keine Events versendet. 
    ''' </summary>
    ''' <param name="Vorgang"></param>
    Sub SetzeStatusNeuUndSendeEvents(Vorgang As VorgangInBearbeitung)
        Dim aktuellerStatus = GetVorgangStatus(Vorgang.Typ, Vorgang.Nummer)
        If IsDBNull(aktuellerStatus) Then
            SetVorgangStatusUndSendeMessageFuerStatus(Vorgang, VorgangStatus.NEU, MitarbeiterID)
        End If
    End Sub

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="Vorgang"></param>
    ''' <param name="Status"></param>
    ''' <param name="button"></param>
    ''' <param name="Zusatztext"></param>
    ''' <remarks></remarks>
    Function SetVorgangStatusUndSendeMessageFuerStatus(Vorgang As VorgangInBearbeitung,
                                    Status As String,
                                    MitarbeiterNr As Integer,
                                    Optional button As Button = Nothing,
                                    Optional Zusatztext As String = "",
                                    Optional MitarbeiterNotifizieren As Boolean = False) As ServiceSMS.KundenNotifizierung
        Try
            If Vorgang Is Nothing Then
                Return Nothing
            End If
            Vorgang.Status = Status
            ModuleGlobal.RequestCommand(New IntraSellVorgangStatusCommand() With {.command = IntraSellCommands.Status, .Typ = Vorgang.Typ, .Nummer = Vorgang.Nummer, .Status = Status}) '(IntraSellCommands.status.ToString & ";" & Vorgang.Typ & ";" & Vorgang.Nummer & ";" & Status)

            If Zusatztext <> "" Then
                ModuleGlobal.RequestCommand(New IntraSellVorgangInfoCommand() With {.command = IntraSellCommands.Info, .Typ = Vorgang.Typ, .Nummer = Vorgang.Nummer, .Info = Zusatztext}) '(IntraSellCommands.status.ToString & ";" & Vorgang.Typ & ";" & Vorgang.Nummer & ";" & Status)
            End If

            If SetVorgangStatus(Vorgang.Typ, Vorgang.Nummer, Status, MitarbeiterNr, silent:=False) Then
                Dim kundenInformieren = CBool(GetVorgangStatusParam(Vorgang.Typ, Status, "KundenInformieren"))
                Dim kopieAnEmail = GetVorgangStatusParam(Vorgang.Typ, Status, "SendeEmailAn")
                Dim kopieAnSMS = GetVorgangStatusParam(Vorgang.Typ, Status, "SendeSMSAn")
                Dim erstelleNachricht = False

                If kundenInformieren Then
                    erstelleNachricht = True
                End If

                If Not IsNull(kopieAnEmail) AndAlso kopieAnEmail.Contains("@") Then
                    erstelleNachricht = True
                End If

                If Not IsNull(kopieAnSMS) AndAlso kopieAnSMS.Length > 5 Then
                    erstelleNachricht = True
                End If

                If Not erstelleNachricht Then
                    Return Nothing
                End If

                Dim ergebnis1 = True
                Dim ergebnis2 = True
                Dim ergebnis3 = True

                Dim nachricht = ErstelleSMSEmailNachricht(Vorgang, Zusatztext)
                If nachricht IsNot Nothing Then
                    OrderPreview.ShowMessage(nachricht.Nachricht)
                    OrderPreview.Show()

                    Dim SendeBericht As String = ""
                    Dim dbgMsg As String = ""

                    If kundenInformieren Then
                        ergebnis1 = SendeNachricht(nachricht, dbgMsg)

                        If ergebnis1 Then
                            SendeBericht += $"SMS/Email an {nachricht.MobileNummerEmpfaenger}/{nachricht.EmailAdresseEmpfaenger} gesendet! Info: {dbgMsg}." & vbNewLine
                        Else
                            SendeBericht += $"SMS/Email an {nachricht.MobileNummerEmpfaenger}/{nachricht.EmailAdresseEmpfaenger} NICHT gesendet! Ergebnis ist {ergebnis1}. Info: {dbgMsg}." & vbNewLine
                        End If
                    Else
                        SendeBericht += $"Kunde wird NICHT informiert. Du kannst es in Maske Menu->Vorgänge->Vorgang Einstellungen umstellen. KundenInformieren ist {kundenInformieren}" & vbNewLine
                    End If

                    'Kopie an die Einstellungen in der Status Tabelle 

                    If Not IsNull(kopieAnEmail) AndAlso kopieAnEmail.Contains("@") Then
                        nachricht.EmailBetreff = nachricht.Nachricht.Split(vbNewLine)(0) 'Erste Zeile 
                        nachricht.EmailAdresseEmpfaenger = kopieAnEmail
                        nachricht.SendEmail = True
                        nachricht.SendSMS = False
                        ergebnis2 = SendeNachricht(nachricht, dbgMsg)
                        If ergebnis2 Then
                            SendeBericht += "Email an " & nachricht.EmailAdresseEmpfaenger & " gesendet! Info: {dbgMsg}." & vbNewLine
                        Else
                            SendeBericht += "Email an " & nachricht.EmailAdresseEmpfaenger & " NICHT gesendet! Info: {dbgMsg}." & vbNewLine
                        End If
                    End If

                    If Not IsNull(kopieAnSMS) AndAlso kopieAnSMS.Length > 5 Then
                        nachricht.MobileNummerEmpfaenger = kopieAnSMS
                        nachricht.SendEmail = False
                        nachricht.SendSMS = True
                        nachricht.MobileNummerAbsender = VarValue_Default(Variablen.FIRMA_WHATSAPP_NUMMER, "436XXXXXXXXX")
                        ergebnis3 = SendeNachricht(nachricht, dbgMsg)

                        If ergebnis3 Then
                            SendeBericht += "SMS an " & nachricht.MobileNummerEmpfaenger & " gesendet! Info: {dbgMsg}." & vbNewLine
                        Else
                            SendeBericht += "SMS an " & nachricht.MobileNummerEmpfaenger & " NICHT gesendet! Info: {dbgMsg}." & vbNewLine
                        End If
                    End If

                    Dim SendenErfolgreich = ergebnis1 AndAlso ergebnis2 AndAlso ergebnis3
                    If MitarbeiterNotifizieren Then
                        SendenErfolgreich = SendenErfolgreich AndAlso SendMessageMitarbeiter(MitarbeiterNr, nachricht, SendeBericht)
                    End If

                    If button IsNot Nothing Then
                        If SendenErfolgreich Then
                            button.BackColor = Color.Green
                        Else
                            button.BackColor = Color.Red
                        End If
                    End If

                    OrderPreview.ShowMessage(SendeBericht & nachricht.Nachricht)
                    OrderPreview.Show()
                    Return nachricht
                End If
            End If
        Catch ex As Exception
            HandleAppError(ex)
        End Try
        Return Nothing
    End Function


    Private Function SendMessageMitarbeiter(MitarbeiterNr As Integer, ByRef nachricht As ServiceSMS.KundenNotifizierung, ByRef SendeBericht As String) As Boolean

        Dim kopieAnEmail = MitarbeiterFeld(MitarbeiterNr, "Email")
        Dim kopieAnSMS = MitarbeiterFeld(MitarbeiterNr, "Mobile")
        If Not IsNull(kopieAnEmail) Or Not IsNull(kopieAnSMS) Then
            nachricht.MobileNummerEmpfaenger = kopieAnSMS
            nachricht.EmailAdresseEmpfaenger = kopieAnEmail
            nachricht.SendEmail = kopieAnEmail.Contains("@")
            nachricht.SendSMS = kopieAnSMS.Length > 6
            Dim debugMsg As String = Nothing
            Dim ergebnis = SendeNachricht(nachricht, debugMsg)
            If ergebnis Then
                SendeBericht += $"Mitarbeiter Email/SMS an {nachricht.EmailAdresseEmpfaenger} gesendet! Info: {debugMsg}" & vbNewLine
                Return True
            Else
                SendeBericht += $"Mitarbeiter Email/SMS an {nachricht.EmailAdresseEmpfaenger} NICHT gesendet! Info: {debugMsg}" & vbNewLine
                Return False
            End If
        End If
        Return False
    End Function


    Sub SetAbgeschlossen(VorgangTyp As String, VorgangNummer As Integer)
        WriteDebug($"SetAbgeschlossen {VorgangTyp}-{VorgangNummer}")
        Dim sqlCheck = <a>SELECT  v.Datum, v.Typ, v.Nummer,v.Abgeschlossen,  a.artnr, a.EAN, a.lagerartikel FROM 
buchvorgang v , `buchvorgang-artikel` va  , grArtikel a
WHERE 
v.Typ = @Typ AND v.Nummer = @Nummer
AND v.Typ = va.Typ 
AND v.Nummer = va.Nummer 
AND (v.Typ = 'AR' OR v.Typ = 'RE')
AND va.ArtNr = a.artnr
AND ( a.lagerartikel = -1 or a.lagerartikel = 1 )
AND NOT EXISTS ( SELECT 1 FROM `grartikel-lagerbewegung` lb WHERE lb.Vorgangstyp = v.Typ AND lb.Vorgangsnummer = v.Nummer and lb.ArtNr = va.ArtNr )
ORDER BY  v.Datum, v.Typ, v.Nummer </a>.Value
        Dim cmdCheck = New MySqlCommand(sqlCheck)

        cmdCheck.Parameters.AddWithValue("Typ", VorgangTyp)
        cmdCheck.Parameters.AddWithValue("Nummer", VorgangNummer)
        Dim check As DataTable = OpenRecordsetInMemory(cmdCheck)
        If check.Rows.Count > 0 Then
            Dim msg = String.Format(Messages.ModuleBuchVorgang_Lagerbuchung_fehlt, VorgangTyp, VorgangNummer, check.Rows(0)("ArtNr"))
            Throw New Exception(msg)
        End If

        Dim cmd = New MySqlCommand("update buchVorgang set abgeschlossen = -1 where Typ=@Typ and Nummer=@Nummer")
        cmd.Parameters.AddWithValue("Typ", VorgangTyp)
        cmd.Parameters.AddWithValue("Nummer", VorgangNummer)
        RunSQL(cmd)
    End Sub

    Sub SetAbgeschlossenEinfach(VorgangTyp As String, VorgangNummer As Integer)
        WriteDebug($"SetAbgeschlossenEinfach {VorgangTyp}-{VorgangNummer}")
        Dim cmd = New MySqlCommand("update buchVorgang set abgeschlossen = 1 where Typ=@Typ and Nummer=@Nummer")
        cmd.Parameters.AddWithValue("Typ", VorgangTyp)
        cmd.Parameters.AddWithValue("Nummer", VorgangNummer)
        RunSQL(cmd)
    End Sub

    Sub SetNichtAbgeschlossen(VorgangTyp As String, VorgangNummer As Integer)
        WriteDebug($"SetNichtAbgeschlossen {VorgangTyp}-{VorgangNummer}")
        Dim cmd = New MySqlCommand("update buchVorgang set abgeschlossen = 0 where Typ=@Typ and Nummer=@Nummer")
        cmd.Parameters.AddWithValue("Typ", VorgangTyp)
        cmd.Parameters.AddWithValue("Nummer", VorgangNummer)
        RunSQL(cmd)
    End Sub

    Sub SetAusgedruckt(VorgangTyp As String, VorgangNummer As Integer)
        WriteDebug($"SetAusgedruckt {VorgangTyp}-{VorgangNummer}")
        Dim cmd = New MySqlCommand("update buchVorgang set ausgedruckt = -1 where Typ=@Typ and Nummer=@Nummer")
        cmd.Parameters.AddWithValue("Typ", VorgangTyp)
        cmd.Parameters.AddWithValue("Nummer", VorgangNummer)
        RunSQL(cmd)

        If ExistsVarValue("ETIKETTEN_DRUCKER_NAME") Then 'Jemand hat schon Etiketten gedruckt, daher fragen wir auch 
            If VorgangTyp = VorgangTypen.AR Then
                'Frage ob Etiketten gedruckt werden sollen nur für AR bei Arfaian
                Dim landISO = GetLieferLandISO2(VorgangTyp, VorgangNummer)
                If IstEULand(landISO) Then
                    Dim achtung As New Achtung
                    achtung.Show()
                    Dim action As New Aktion() With {.ButtonText = "Etiketten drucken"}
                    action.Params = New List(Of Object)
                    action.Params.Add(VorgangTyp)
                    action.Params.Add(VorgangNummer)
                    achtung.ShowMessage("EU Land", "Lieferland " & landISO & " ist ein EU Land. Wollen Sie Etiketten ausdrucken?", Aktion:=action)
                    AddHandler achtung.OnAktion, AddressOf EtikettenDrucken
                End If
            End If
        End If

    End Sub

    Sub EtikettenDrucken(ByRef Aktion As Aktion)
        Dim vorgang = New VorgangInBearbeitung(Aktion.Params(0), Aktion.Params(1))
        SendeIntraSellVorgangCommand(vorgang)
    End Sub

    Sub SendeIntraSellVorgangCommand(vorgang As VorgangInBearbeitung)
        Dim cmd As New IntraSellVorgangCommand
        cmd.Nummer = vorgang.Nummer
        cmd.Typ = vorgang.Typ
        cmd.command = IntraSellCommands.EtikettenDruck
        ModuleGlobal.RequestCommandDirekt(cmd)
    End Sub

    Sub SendeIntraSellVorgangCommandVersand(vorgang As VorgangInBearbeitung)
        Dim cmd As New IntraSellVorgangCommand
        cmd.Nummer = vorgang.Nummer
        cmd.Typ = vorgang.Typ
        cmd.command = IntraSellCommands.VersandBerechnen
        ModuleGlobal.RequestCommandDirekt(cmd)
    End Sub

    Sub SetNichtAusgedruckt(VorgangTyp As String, VorgangNummer As Integer)
        Dim cmd = New MySqlCommand("update buchVorgang set ausgedruckt = 0 where Typ=@Typ and Nummer=@Nummer")
        cmd.Parameters.AddWithValue("Typ", VorgangTyp)
        cmd.Parameters.AddWithValue("Nummer", VorgangNummer)
        RunSQL(cmd)
    End Sub

    Sub SetBezahlt(VorgangTyp As String, VorgangNummer As Integer)
        WriteLog($"SetBezahlt {VorgangTyp}-{VorgangNummer}")
        Dim cmd = New MySqlCommand("update buchVorgang set bezahlt = -1 where Typ=@Typ and Nummer=@Nummer")
        cmd.Parameters.AddWithValue("Typ", VorgangTyp)
        cmd.Parameters.AddWithValue("Nummer", VorgangNummer)
        RunSQL(cmd)
    End Sub


    Public Function GetBetragEingang(VorgangTyp As String, VorgangNummer As Integer)
        WriteLog($"GetBetragEingang {VorgangTyp}-{VorgangNummer}")
        Dim cmdBezahlt = New MySqlCommand("select sum(BetragEingang) from buchKassabuch where  VorgangTyp=@Typ and VorgangNummer=@Nummer")
        cmdBezahlt.Parameters.AddWithValue("Typ", VorgangTyp)
        cmdBezahlt.Parameters.AddWithValue("Nummer", VorgangNummer)
        Return FirstRow(cmdBezahlt)
    End Function

    Sub SetBezahltLautKassenbuchungen(VorgangTyp As String, VorgangNummer As Integer)
        WriteLog($"SetBezahltLautKassenbuchungen {VorgangTyp}-{VorgangNummer}")
        Dim summeBezahlt = GetBetragEingang(VorgangTyp, VorgangNummer)
        Dim cmd = New MySqlCommand("update buchVorgang set bezahlt = -1 where Typ=@Typ and Nummer=@Nummer and SummeBrutto<=@summeBezahlt")
        cmd.Parameters.AddWithValue("Typ", VorgangTyp)
        cmd.Parameters.AddWithValue("Nummer", VorgangNummer)
        cmd.Parameters.AddWithValue("summeBezahlt", summeBezahlt)
        RunSQL(cmd)
    End Sub

    Sub SetVorgangFeld(VorgangTyp As String, VorgangNummer As Integer, Feld As String, Wert As String)
        Dim cmd = New MySqlCommand($"update buchVorgang set {Feld} = @Wert where Typ=@Typ and Nummer=@Nummer")
        cmd.Parameters.AddWithValue("Typ", VorgangTyp)
        cmd.Parameters.AddWithValue("Nummer", VorgangNummer)
        cmd.Parameters.AddWithValue("Wert", Wert)
        RunSQL(cmd)
    End Sub

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="VorgangTyp"></param>
    ''' <param name="VorgangNummer"></param>
    ''' <param name="kundNr2">nothing oder Indeger</param>
    ''' <remarks></remarks>
    Sub SetLieferadresse(VorgangTyp As String, VorgangNummer As Integer, KundNr As Integer, KundNr2 As Object)

        If KundNr2 = 0 Then
            KundNr2 = Nothing
        End If

        If Not IsNothing(KundNr2) Then
            Dim cmd1 = New MySqlCommand("select IDNR from `ofAdressen-weitere` WHERE ID=@ID")
            cmd1.Parameters.AddWithValue("ID", KundNr2)
            Dim checkIDNR = FirstRow(cmd1)
            If checkIDNR <> KundNr Then
                Dim msg = String.Format("Diese weitere Adresse mit der ID {0} gehört nicht zum Kunden mit der IDNR {1}", KundNr2, KundNr)
                Throw New Exception(msg)
            End If
        End If

        Dim cmd = New MySqlCommand("update buchVorgang set KundNr2=@KundNr2 where Typ=@Typ and Nummer=@Nummer")
        cmd.Parameters.AddWithValue("KundNr2", KundNr2)
        cmd.Parameters.AddWithValue("Typ", VorgangTyp)
        cmd.Parameters.AddWithValue("Nummer", VorgangNummer)
        RunSQL(cmd)
    End Sub

    Function GetLieferLandISO2(VorgangTyp As String, VorgangNummer As Integer) As String
        Dim cmd = New MySqlCommand("select l.ISO2 from `buchVorgang` v, `ofAdressen-weitere` a, grLand l where v.Typ=@Typ and v.Nummer=@Nummer and v.KundNr2=a.ID and a.Land=l.IDNR")
        cmd.Parameters.AddWithValue("Typ", VorgangTyp)
        cmd.Parameters.AddWithValue("Nummer", VorgangNummer)
        Dim landISO2 = FirstRow(cmd)
        If landISO2 <> NOT_AVAILABLE And landISO2 IsNot Nothing Then
            Return landISO2
        End If

        Dim cmd1 = New MySqlCommand("select l.ISO2 from `buchVorgang` v, `ofAdressen` a, grLand l where v.Typ=@Typ and v.Nummer=@Nummer and v.KundNr=a.IDNR and a.Land=l.IDNR")
        cmd1.Parameters.AddWithValue("Typ", VorgangTyp)
        cmd1.Parameters.AddWithValue("Nummer", VorgangNummer)
        landISO2 = FirstRow(cmd1)
        Return landISO2
    End Function

    Function GetLieferLandISO2NachKunden(KundenNr As Integer) As String
        Dim cmd1 = New MySqlCommand("select l.ISO2 from  `ofAdressen` a, grLand l where a.IDNR=@KundenNr and a.Land=l.IDNR")
        cmd1.Parameters.AddWithValue("KundenNr", KundenNr)
        Dim landISO2 = FirstRow(cmd1)
        Return landISO2
    End Function

    Function GetVorgangPreisliste(Vorgang As VorgangInBearbeitung) As String
        Dim KundenPreisliste = KundePreisliste(idnr:=Vorgang.KundNr)
        If IsDBNull(KundenPreisliste) Then
            Return Vorgang.LieferMethode
        End If
        If KundenPreisliste <> "" Then
            Return KundenPreisliste
        Else
            Return Vorgang.LieferMethode
        End If
    End Function

    ''' <summary>
    ''' Mitarbeiter Status im Vorgang setzen, wenn noch nicht gesetzt
    ''' </summary>
    ''' <param name="Typ"></param>
    ''' <param name="Nummer"></param>
    ''' <param name="MitarbeiterNr"></param>
    ''' <remarks></remarks>
    Public Sub SetMitarbeiter(Typ As String, Nummer As String, MitarbeiterNr As Integer)
        Dim cmd = New MySqlCommand("update buchVorgang set MitarbeiterNr=@MitarbeiterNr where (MitarbeiterNr is null or  MitarbeiterNr=0) and Typ=@Typ and Nummer=@Nummer")
        cmd.Parameters.AddWithValue("MitarbeiterNr", MitarbeiterNr)
        cmd.Parameters.AddWithValue("Typ", Typ)
        cmd.Parameters.AddWithValue("Nummer", Nummer)
        RunSQL(cmd)
    End Sub


    ''' <summary>
    ''' TODO: Problem ist hier dass nicht gleichzeitig Pizza und Bar ausgedruckt werden kann.
    ''' </summary>
    ''' <param name="vorgangInBearbeitung"></param> 
    ''' <param name="Ziel">Kueche, Bar, Pizza - Hängt mit dem Drucker wo welchen Drucker gibt, oder ALLE wenn alle Drucker auf einmal zu beauftragen sind</param> 
    ''' <remarks></remarks>
    Public Function AuftragKueche(vorgangInBearbeitung As VorgangInBearbeitung, Ziel As String) As String
        Try
            WriteLog($"AuftragKueche Vorgang {vorgangInBearbeitung} mit Ziel {Ziel}")
            Dim content As String = Nothing
            Dim filter = "(Status is null or Stk<>Packung)"
            'Check if there are open positions
            Dim sql = "select ak.Drucker as DruckerZiel, count(*) as AnzahlPos from `buchVorgang-artikel` va, grArtikel a, `grArtikel-Kategorien` ak " &
                                                       " where va.ArtNr = a.ArtNr and a.ArtKatNr = ak.ArtKatNr and Nummer=@Nummer and Typ=@Typ and " & filter &
                                                       " group by DruckerZiel"
            Dim cmd As New MySqlCommand(sql)
            cmd.Parameters.AddWithValue("Nummer", vorgangInBearbeitung.Nummer)
            cmd.Parameters.AddWithValue("Typ", vorgangInBearbeitung.Typ)
            Dim PositioneFuerKueche = OpenRecordsetInMemory(cmd)
            For Each r In PositioneFuerKueche.Rows
                Dim anzPos As Integer = r("AnzahlPos")
                Dim DruckerZiel As String = ""

                If Not IsDBNull(r("DruckerZiel")) Then
                    DruckerZiel = r("DruckerZiel")
                End If
                If IsNumeric(anzPos) AndAlso anzPos > 0 Then
                    If Ziel = "ALLE" OrElse (Ziel = DruckerZiel) Then
                        Dim vorlage = VORLAGE_INFO
                        If File.Exists("Vorlagen\Vorgang_Info_" & DruckerZiel & ".txt") Then
                            vorlage = "Vorlagen\Vorgang_Info_" & DruckerZiel & ".txt"
                        End If

                        Dim filterZiel As String = filter & " and va.artNr in (select a.artNr from grArtikel a where a.ArtKatNr in (select ak.ArtKatNr from `grArtikel-Kategorien` ak where  a.ArtKAtNr = ak.ArtKatNr and (ak.Drucker is null or ak.Drucker='" & DruckerZiel & "') ))"
                        Dim vorgangInfo As String = OpenAusdruck_InWord_Filename_RTF(vorgangInBearbeitung.Typ,
                                                                                                            vorgangInBearbeitung.Nummer,
                                                                                                            vorlage,
                                                                                                            True,
                                                                                                            filterZiel,
                                                                                                            DruckerZiel)
                        If File.Exists(vorgangInfo) Then
                            content = File.ReadAllText(vorgangInfo)
                            RaiseEvent VorgangKuecheEvent(vorgangInBearbeitung, content)
                        End If

                        'Print 
                        Dim PRINT_PORT = VarValue_Default("PRINT_PORT_" & DruckerZiel, VarValue_Default(Variablen.PRINT_PORT, "/d:lpt3"))
                        If DruckerZiel = "" Then
                            PRINT_PORT = VarValue_Default("PRINT_PORT", "/d:lpt3")
                        End If
                        PrintFile(vorgangInfo, PRINT_PORT)

                        'Küchenaufträge auf Drucker für Kellner drucken 'Coconut
                        If ExistsVarValue(Variablen.PRINT_KUECHE_AM_STANDARD) AndAlso VarValue(Variablen.PRINT_KUECHE_AM_STANDARD) Then
                            If DruckerZiel.ToUpper() = "KUECHE" Then
                                Dim PRINT_PORT_KELLNER = VarValue_Default("PRINT_PORT", "/d:lpt3")
                                PrintFile(vorgangInfo, PRINT_PORT_KELLNER)
                            End If
                        End If

                        If DruckerZiel <> "" Then
                                cmd = New MySqlCommand("update buchVorgang set Status=@Status where Nummer=@Nummer and Typ=@Typ")
                                cmd.Parameters.AddWithValue("Status", DruckerZiel)
                                cmd.Parameters.AddWithValue("Nummer", vorgangInBearbeitung.Nummer)
                                cmd.Parameters.AddWithValue("Typ", vorgangInBearbeitung.Typ)
                                RunSQL(cmd)
                            End If

                            cmd = New MySqlCommand("update `buchVorgang-artikel` va set va.Status=@Status, va.Packung=Stk where " & filterZiel & " and va.Nummer=@Nummer and va.Typ=@Typ")
                            cmd.Parameters.AddWithValue("Status", DruckerZiel)
                            cmd.Parameters.AddWithValue("Nummer", vorgangInBearbeitung.Nummer)
                            cmd.Parameters.AddWithValue("Typ", vorgangInBearbeitung.Typ)
                            RunSQL(cmd)
                        End If
                    End If
            Next

            Return content
        Catch ex As Exception
            HandleAppError(ex)
        End Try
        Return Nothing
    End Function

    Public Sub DefiniereVorgangAktion(VorgangTyp As String, Status As String)
        Dim va As New VorgangAktion
        va.Show()
        va.ShowStatus(VorgangTyp, Status)
        va.BringToFront()
        'va.TopMost = True
    End Sub

    Function LadeVorgangRow(Typ As String, Nummer As Integer) As dsVorgaenge.buchvorgangRow
        Dim ta As New dsVorgaengeTableAdapters.buchvorgangTableAdapter
        Dim data As dsVorgaenge.buchvorgangDataTable = ta.GetDataByNummer(Typ, Nummer)
        If data.Rows.Count = 1 Then
            Dim vorg As dsVorgaenge.buchvorgangRow = data.Rows(0)
            Dim gegebenBar = intrasell.vorgang.GetVorgangEigenschaft(Typ, Nummer, BARGELD_GEGEBEN)
            If IsNumeric(gegebenBar) Then
                vorg.GegebenBar = gegebenBar
            Else
                vorg.GegebenBar = 0
            End If
            Return vorg
        Else
            Return Nothing
        End If
    End Function

    Function LadeVorgang(Typ As String, Nummer As Integer) As VorgangInBearbeitung
        Dim vorgangRow As dsVorgaenge.buchvorgangRow = LadeVorgangRow(Typ, Nummer)
        If vorgangRow Is Nothing Then
            Return Nothing
        End If

        Dim vorgang = New VorgangInBearbeitung(vorgangRow)
        If Not vorgangRow.IsMitarbeiterNrNull Then
            vorgang.MitarbeiterNr = vorgangRow.MitarbeiterNr
        End If
        If Not vorgangRow.IsZahlungsMethodeNull Then
            vorgang.ZahlungsMethode = vorgangRow.ZahlungsMethode
        End If
        If Not vorgangRow.IsTransportMethodeNull Then
            vorgang.LieferMethode = vorgangRow.TransportMethode
        End If

        If Not vorgangRow.IsWoherNull Then
            vorgang.Woher = vorgangRow.Woher
        End If

        If Not vorgangRow.IsWohinNull Then
            vorgang.Wohin = vorgangRow.Wohin
        End If

        Return vorgang
    End Function


    ''' <summary>
    ''' Beim Schliessen der EasyKassa sollte die letzte nicht benutzte Rechnungsnummer wieder freigegeben werden.
    ''' </summary>
    ''' <remarks></remarks>
    Sub LoescheLetzteNichtBenutzteNummer(typ As String)
        Dim sql As String
        sql = $"SELECT Nummer FROM buchVorgang v where v.Typ='{typ}' 
                and v.Datum = (select max(Datum) from buchVorgang where  Typ='{typ}')  
                and not exists (select 1 from `buchVorgang-Artikel` where Nummer=v.Nummer and Typ=v.Typ)"
        Dim letzteNummer = FirstRow(sql)
        If letzteNummer IsNot Nothing Then
            sql = $"delete from buchVorgang where Typ='{typ}' and nummer={letzteNummer}"
            RunSQL(sql)
        End If
    End Sub

    ''' <summary>
    ''' Wird von IntraSell Web für HAndy Bonieren benutzt
    ''' </summary>
    ''' <param name="vorgangInBearbeitung"></param>
    ''' <remarks></remarks>
    Public Function KassaAbschliessenFuerHandy(vorgangInBearbeitung As VorgangInBearbeitung) As Boolean
        Try
            AddTask(ModuleTasks.VorgangAbschliessenBar, vorgangInBearbeitung.Typ & "-" & vorgangInBearbeitung.Nummer)
        Catch ex As Exception
            Dim msg = String.Format(Messages.ModuleBuchVorgang_kann_nicht_abgeschlossen_werden, vorgangInBearbeitung.Typ, vorgangInBearbeitung.Nummer, ex.Message)
            HandleAppError(ex, msg, True)
            Return False
        End Try
        Return True
    End Function

    ''' <summary>
    ''' Warte bis Beleg signiert wird und dann druck 
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub WarteAufSignierungDruckTask(warteAufSignierungDruckVorgang As VorgangInBearbeitung)
        Try

            Dim cnt = 0
            If IsNothing(warteAufSignierungDruckVorgang) Then
                Return
            End If
            While cnt < 10
                WriteLog("warteAufSignierungDruckTask " & cnt)
                Thread.Sleep(1000)
                cnt += 1

                Try

                    Dim vorgDruck = New VorgangInBearbeitung(warteAufSignierungDruckVorgang.Typ, warteAufSignierungDruckVorgang.Nummer, warteAufSignierungDruckVorgang.KundNr, warteAufSignierungDruckVorgang.Notiz)

                    'Rechnung holen
                    If vorgDruck.Typ = VorgangTypen.AU Then
                        Dim woher = vorgDruck.Typ & vorgDruck.Nummer
                        'Check if bereits so konvertiert 
                        Dim Sql As String = "SELECT Nummer FROM buchVorgang WHERE Typ='" & VorgangTypen.AR & "' and woher='" & woher & "'"
                        Dim WohinNummer = FirstRow(Sql)
                        If IsNumeric(WohinNummer) Then
                            vorgDruck = New VorgangInBearbeitung(VorgangTypen.AR, WohinNummer, warteAufSignierungDruckVorgang.KundNr, warteAufSignierungDruckVorgang.Notiz)
                        End If

                        If IstVorgangAbgeschlossen(vorgDruck.Typ, vorgDruck.Nummer) Then
                            VorgangDrucken(vorgDruck.Typ, vorgDruck.Nummer, isUeberleitung:=False, showPreview:=VarValue_Default(PRINT_AM_BILDSCHIRM, False))
                            Return
                        End If
                    Else
                        If IstVorgangAbgeschlossen(vorgDruck.Typ, vorgDruck.Nummer) Then
                            VorgangDrucken(vorgDruck.Typ, vorgDruck.Nummer, isUeberleitung:=False, showPreview:=VarValue_Default(PRINT_AM_BILDSCHIRM, False))
                            Return
                        End If
                    End If

                Catch ex As Exception
                    HandleAppError(ex, "Will weiter probieren nach Fehler in warteAufSignierungDruckTask", Silent:=True)
                End Try

            End While
        Catch ex As Exception
            HandleAppError(ex, "Fehler in warteAufSignierungDruckTask", Silent:=True)
        End Try
    End Sub

#Region "Summen"

    ''' <summary>
    ''' liefert die Brutto summe eines vorganges
    ''' </summary>
    ''' <param name="VorgangTyp"></param>
    ''' <param name="VorgangNummer"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function GetSummeVorgang(VorgangTyp As String, VorgangNummer As Integer) As Decimal
        Dim sql As String = "Select Sum(Stk*Preis_Brutto) as Summe FROM `buchVorgang-Artikel` " &
              " where Nummer = @VorgangNummer and Typ = @VorgangTyp"

        Dim cmd = New MySqlCommand(sql)
        cmd.Parameters.AddWithValue("VorgangNummer", VorgangNummer)
        cmd.Parameters.AddWithValue("VorgangTyp", VorgangTyp)

        Dim summe = FirstRow(cmd)
        If IsNumeric(summe) Then
            Return summe
        End If
        Return 0
    End Function

    ''' <summary>
    ''' liefert das Gesamtgewicht eines Vorganges
    ''' </summary>
    ''' <param name="VorgangTyp"></param>
    ''' <param name="VorgangNummer"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetGesamtgewichtVorgang(VorgangTyp As String, VorgangNummer As Integer) As Decimal
        Dim sql As String = "Select round(Sum( Gewicht*Stk ),2) as Summe FROM `buchVorgang-Artikel` va, grArtikel a " &
             " where va.ArtNr = a.ArtNr and va.Nummer = @VorgangNummer and va.Typ = @VorgangTyp"

        Dim cmd = New MySqlCommand(sql)
        cmd.Parameters.AddWithValue("VorgangNummer", VorgangNummer)
        cmd.Parameters.AddWithValue("VorgangTyp", VorgangTyp)

        Dim summe = FirstRow(cmd)
        If IsNumeric(summe) Then
            Return CDec(summe)
        Else
            Return 0
        End If
    End Function

    Public Sub SetSummeVorgang(VorgangTyp As String, VorgangNummer As Integer)
        intrasell.vorgang.SetSummeVorgang(VorgangTyp, VorgangNummer, FunctionsDB.CurrentDB)
    End Sub

    Class Summen
        Property item1 As Decimal
        Property item2 As Decimal

        Public Sub New(item1, item2)
            Me.item1 = item1
            Me.item2 = item2
        End Sub

    End Class

    ''' <summary>
    ''' Vorgang Summen neu anhand der Position berechnen. 
    ''' </summary>
    ''' <param name="vorgang"></param>
    ''' <remarks></remarks>
    Public Sub BerechneVorgangSummen(Vorgang As dsVorgaenge.buchvorgangRow)
        Try
            Debug.Print("BerechneVorgangSummen")

            Dim summeNetto As Decimal = 0.0, summeBrutto As Decimal = 0.0
            Dim gesamtgewicht As Decimal = 0

            Dim p = From pos In Vorgang._Getbuchvorgang_artikelRows
                    Group By pos.MWSTSatz Into g = Group
                    Select New Summen(g.Sum(Function(item) item.Stk * item.Preis_Brutto) * 100 / (100 + g.ElementAt(0).MWSTSatz), g.Sum(Function(item) item.Stk * item.Preis_Brutto))

            summeNetto = Math.Round(p.Sum(Function(item) item.item1), 2, MidpointRounding.AwayFromZero)
            summeBrutto = Math.Round(p.Sum(Function(item) item.item2), 2, MidpointRounding.AwayFromZero)

            For Each pos In Vorgang._Getbuchvorgang_artikelRows
                Try
                    gesamtgewicht += RoundUp(pos.Stk * ArtikelGewicht(pos.ArtNr), 2)
                Catch ex As Exception
                    Debug.Print("Fehler in BerechneVorgangSummen: " & ex.Message)
                    WriteLog("Fehler in BerechneVorgangSummen: " & ex.Message)
                End Try
            Next

            Dim SetzeSumme = True
            If Not Vorgang.IsSummeNull AndAlso Vorgang.Summe = summeNetto AndAlso Vorgang.SummeBrutto = summeBrutto Then
                SetzeSumme = False
            End If

            Dim SetzeGesamtgewicht = True
            If Not Vorgang.IsGesamtgewichtNull AndAlso Vorgang.Gesamtgewicht = gesamtgewicht Then
                SetzeGesamtgewicht = False
            End If

            If SetzeSumme Then
                'TODO: ACHTUNG !!! die positionszeile wird zurückgesetzt wenn Vorgang.Summe gesetzt wird, also diese Funktion nur dann aufrufen wenn die Zeile inserted wurde.
                'Debug.Print("Neue Summe Netto " & CStr(summeNetto))
                Try
                    Vorgang.Summe = FormatCurrency(summeNetto, PREIS_GENAUIGKEIT)
                Catch ex As Exception
                    HandleAppError(ex, Silent:=True)
                End Try
                Try
                    Vorgang.SummeBrutto = FormatCurrency(summeBrutto, PREIS_GENAUIGKEIT)
                Catch ex As Exception
                    HandleAppError(ex, Silent:=True)
                End Try
                Try
                    Vorgang.SummeMWST = FormatCurrency(summeBrutto - summeNetto, PREIS_GENAUIGKEIT)
                Catch ex As Exception
                    HandleAppError(ex, Silent:=True)
                End Try
            End If

            If SetzeGesamtgewicht Then
                Try
                    Vorgang.Gesamtgewicht = gesamtgewicht
                Catch ex As Exception
                    HandleAppError(ex, Silent:=True)
                End Try
            End If


            Dim SetzeGegebenBar = VarValue_Default(BARRECHNUNG_KEINE_EINGABE_BAR_GEGEBEN, "true")
            If Not Vorgang.IsGegebenBarNull AndAlso Vorgang.GegebenBar = Vorgang.SummeBrutto Then
                SetzeGegebenBar = False
            End If

            If SetzeGegebenBar Then
                Try
                    Vorgang.GegebenBar = Vorgang.SummeBrutto
                Catch ex As Exception
                    HandleAppError(ex, Silent:=True)
                End Try
            End If
        Catch ex As Exception
            HandleAppError(ex, Silent:=True)
        End Try

    End Sub

#End Region

End Module
