﻿<?xml version="1.0" encoding="utf-8"?>
<configset name="VatChange2024" author="THO-intusdata">
  <comment />
  <requirements />
  <references />
  <objects>
    <object class="ZusatzfeldKlasse" alias="ZusatzfeldKlasse0">
      <member name="Expression">Zusatzklasse28.allinstances</member>
      <member name="Klassen">ScriptEintrag</member>
      <member name="FieldName">Modul</member>
      <member name="Bezeichnung">
        <mltext language="DE">Modul</mltext>
        <mltext language="FR">Modules</mltext>
      </member>
      <member name="FieldType">Object</member>
      <member name="Hidden">false</member>
      <member name="OrderIdx">0</member>
      <member name="Auswahltyp">Object</member>
      <field name="Kopieren">false</field>
    </object>
    <object class="ScriptEintrag" alias="ScriptEintrag_Event-Rechnungdatumupdate-VATratecheck0">
      <member name="EintragID">ScriptEventInvoiceUpdateCheckVatRate</member>
      <member name="Bezeichnung">Event - Rechnung datum update - VAT rate check</member>
      <member name="EventMembers">datum, von, bis</member>
      <member name="EventClass">Rechnung</member>
      <member name="ContainerScript">false</member>
      <member name="ScriptText"># coding: UTF-8
# ---------------------------------------------------------------------------------------------------------------------------------
# Event - Rechnung datum update - VAT rate check
# ---------------------------------------------------------------------------------------------------------------------------------
#           Version: v.0.9.1
#              Date: 9 novembre 2023
#               Ref: raoul.gendroz@intusdata.ch 
# ---------------------------------------------------------------------------------------------------------------------------------
#   Fonctionnalités: affiche un message d'avertissement lors de la modification d'une date de facture 
#                    - facture 2023 comportant des prestations 2024
#                    - facture 2024 comportant des prestations 2023
#                    - facture 2023 avec un taux par défaut de 8.1
#                    - facture 2024 avec un taux par défaut de 7.7
# ---------------------------------------------------------------------------------------------------------------------------------
#      Last updates: n/a
# ---------------------------------------------------------------------------------------------------------------------------------
#         Prérequis: - script 'Adapter le taux de TVA'
#                    - script 'Event - Rechnung new - VAT rate check'
# ---------------------------------------------------------------------------------------------------------------------------------
#             Class: Rechnung    
#         Condition: n/a
#      ObjectScript: n/a
#   ContainerScript: n/a
#         EventType: Modification
#        EventClass: Rechnung
#      EventMembers: datum, von, bis
#    ExtendedRights: no
# ---------------------------------------------------------------------------------------------------------------------------------

import vtcapp, datetime

def main():
  # get rechnung 
  rechnung = argobject
  
  # get number leistung year
  nb2023 = rechnung.eval("self.leistungen-&gt;select(datum-&gt;formatdatetime('yyyy')='2023')-&gt;size")
  nb2024 = rechnung.eval("self.leistungen-&gt;select(datum-&gt;formatdatetime('yyyy')='2024')-&gt;size")

  # get invoice date
  year = rechnung.eval("self.datum-&gt;formatdatetime('yyyy')")

  # tests
  if(year=='2023')and(nb2024&gt;0):
    vtcapp.msgbox("ATTENTION: "+str(nb2024)+ " prestations 2024 présentes dans la facture "+str(year)+".\nVeuillez vérifier que les taux de TVA soient corrects et au besoin lancer le script \n'Adapter le taux de TVA'.")
    return

  if(year=='2024')and(nb2023&gt;0):
    vtcapp.msgbox("ATTENTION: "+str(nb2023)+ " prestations 2023 présentes dans la facture "+str(year)+".\nVeuillez vérifier que les taux de TVA soient corrects et au besoin lancer le script \n'Adapter le taux de TVA'.")
    return

  # get invoice mwst default rate
  vatrate = rechnung.eval("self.leistMWSTSatz")

  if((year=='2023')and(vatrate != 7.7)) or ((year=='2024')and(vatrate != 8.1)):

    vtcapp.msgbox("ATTENTION: le taux de TVA ("+ str(vatrate) +"%) de la facture ne correspond pas à l'année de la facture "+str(year)+".\nVeuillez vérifier que les taux de TVA soient corrects et au besoin lancer le script \n'Adapter le taux de TVA'.")
    return

main()</member>
      <member name="EventType">Changed</member>
      <member name="ObjectScript">false</member>
      <member name="ExtendedRights">false</member>
      <member name="SelectedObjectsScript">false</member>
      <member name="Platform">Python</member>
    </object>
    <object class="ScriptEintrag" alias="ScriptEintrag_Event-Rechnungnew-VATratecheck1">
      <member name="EintragID">ScriptEventNewInvoiceCheckVatRate</member>
      <member name="Bezeichnung">Event - Rechnung new - VAT rate check</member>
      <member name="EventClass">Rechnung</member>
      <member name="ContainerScript">false</member>
      <member name="ScriptText"># coding: UTF-8
# ---------------------------------------------------------------------------------------------------------------------------------
# Event - Rechnung new - VAT rate check
# ---------------------------------------------------------------------------------------------------------------------------------
#           Version: v.0.9.0
#              Date: 9 novembre 2023
#               Ref: raoul.gendroz@intusdata.ch 
# ---------------------------------------------------------------------------------------------------------------------------------
#   Fonctionnalités: affiche un message d'avertissement lors de création d'une date de facture 
#                    - facture 2023 comportant des prestations 2024
#                    - facture 2024 comportant des prestations 2023
#                    - facture 2023 avec un taux par défaut de 8.1
#                    - facture 2024 avec un taux par défaut de 7.7
# ---------------------------------------------------------------------------------------------------------------------------------
#      Last updates: n/a
# ---------------------------------------------------------------------------------------------------------------------------------
#         Prérequis: - script 'Adapter le taux de TVA'
#                    - script 'Event - Rechnung datum update - VAT rate check'
# ---------------------------------------------------------------------------------------------------------------------------------
#             Class: Rechnung    
#         Condition: n/a
#      ObjectScript: n/a
#   ContainerScript: n/a
#         EventType: Nouveau
#        EventClass: Rechnung
#      EventMembers: n/a
#    ExtendedRights: no
# ---------------------------------------------------------------------------------------------------------------------------------

import vtcapp, datetime

def main():
  # get rechnung 
  rechnung = argobject
  
  # get number leistung year
  nb2023 = rechnung.eval("self.leistungen-&gt;select(datum-&gt;formatdatetime('yyyy')='2023')-&gt;size")
  nb2024 = rechnung.eval("self.leistungen-&gt;select(datum-&gt;formatdatetime('yyyy')='2024')-&gt;size")

  # get invoice date
  year = rechnung.eval("self.datum-&gt;formatdatetime('yyyy')")

  # tests
  if(year=='2023')and(nb2024&gt;0):
    vtcapp.msgbox("ATTENTION: "+str(nb2024)+ " prestations 2024 présentes dans la facture "+str(year)+".\nVeuillez vérifier que les taux de TVA soient corrects et au besoin lancer le script \n'Adapter le taux de TVA'.")
    return

  if(year=='2024')and(nb2023&gt;0):
    vtcapp.msgbox("ATTENTION: "+str(nb2023)+ " prestations 2023 présentes dans la facture "+str(year)+".\nVeuillez vérifier que les taux de TVA soient corrects et au besoin lancer le script \n'Adapter le taux de TVA'.")
    return

  # get invoice mwst default rate
  vatrate = rechnung.eval("self.leistMWSTSatz")

  if((year=='2023')and(vatrate != 7.7)) or ((year=='2024')and(vatrate != 8.1)):

    vtcapp.msgbox("ATTENTION: le taux de TVA ("+ str(vatrate) +"%) de la facture ne correspond pas à l'année de la facture "+str(year)+".\nVeuillez vérifier que les taux de TVA soient corrects et au besoin lancer le script \n'Adapter le taux de TVA'.")
    return

main()</member>
      <member name="EventType">Create</member>
      <member name="ObjectScript">false</member>
      <member name="ExtendedRights">false</member>
      <member name="SelectedObjectsScript">false</member>
      <member name="Platform">Python</member>
    </object>
    <object class="ScriptEintrag" alias="ScriptEintrag_DéfinirtauxTVA2">
      <member name="EintragID">ScriptSetVat</member>
      <member name="Bezeichnung">Définir taux TVA</member>
      <member name="Klassen">Rechnung</member>
      <member name="ContainerScript">false</member>
      <member name="ScriptText"># coding: UTF-8
#
#---Bezeichnung: MwstTyp setzen
#   Klassen: Rechnung
#   CondExpression:
#   ObjectScript: Y
#   ContainerScript: N
#   EventType: Kein
#   EventClass:
#   EventMembers:
#   ExtendedRights: N
#
#---Neuer Mwst Typ für Leistungen, Spesen, Auslagen setzen.
#
#---07.09.2010, MR: Erstellt.
#   11.10.2010, MR: Objekte mit MwstSatz 0 werden durch das Script
#                   nicht verändert. Auswahl Msttyp Satz=0 wird nicht mehr angezeigt.
#   28.09.2017, STH: Umgeschrieben für MWST-Umstellung auf 7.7%.
#   01.11.2023, THO-ID: Traduction FR

Version = 107

import vtcapp
import datetime

def Main(rech):
    version = vtcapp.versiontointeger(vtcapp.evalocl("DbVersion.allinstances-&gt;first.version"))
    mwsttypen = vtcapp.evalocl("Mwsttyp.allinstances-&gt;reject(satz=0)")
    if rech.istypeof('Rechnung') and not rech.verrechnet:
        if (version &gt;= 6100000):
            # Varianten mit Python Dialogen (ab Version 6.1)
            dlgDefinition="""
            &lt;Dialog Title="Définir un nouveau type de TVA" Width="300"&gt;
            &lt;TextBlock Text="Concerne: Prestations, frais et dépenses" Appearance="Info"/&gt;
            &lt;DatePicker Name="DatumVon" Label="Du" /&gt;
            &lt;DatePicker Name="DatumBis" Label="Au" /&gt;
            &lt;ComboBox Name="MwstTyp" Label="Nouveau type de TVA" ListExpression="MwstTyp.allinstances-&gt;select(aktiv)-&gt;reject(satz=0)" /&gt;
            &lt;Dialog.Buttons&gt;
                &lt;Button Text="OK" IsAccept="True" Command="{Binding OkCommand}" /&gt;
                &lt;Button Text="Cancel" IsCancel="True" Command="{Binding CancelCommand}" /&gt;
            &lt;/Dialog.Buttons&gt;
            &lt;/Dialog&gt;
            """
            if (version &lt; 6100014):
                # Versionen vor 6.1.0.14: Python Dialog, aber ohne Datumsunterstützung
                vonDatum = argobject.eval('date.firstofquarter')
                bisDatum = argobject.eval('date.lastofquarter')
                von = (vonDatum-datetime.datetime(1970, 1, 1)).total_seconds() * 1000
                bis = (bisDatum-datetime.datetime(1970, 1, 1)).total_seconds() * 1000

                initValues={}
                initValues["DatumVon"] = "/Date(%i)/" % von
                initValues["DatumBis"] = "/Date(%i)/" % bis
            if (version &gt;= 6100014):
                # Versionen ab 6.1.0.14
                initValues={}
                initValues["DatumVon"] = argobject.eval('date.firstofquarter')
                initValues["DatumBis"] = argobject.eval('date.lastofquarter')

            showDialog = True
            while showDialog:
                ok, von, bis, mwstid = showPythonDialog(dlgDefinition, initValues, version)
                showDialog = ok and (von &gt; bis)
                if showDialog:
                    vtcapp.msgbox("La date de début ne doit pas être supérieure à la date de fin..")

            if ok:
                if mwstid:
                    if von.year == 1:
                        von = datetime.datetime(1900,1,1)
                    if bis.year == 1:
                        bis = datetime.datetime(2050,12,31)

                    s = "Mwsttyp.allinstances-&gt;select(boldid=" + str(mwstid) + ")-&gt;first"
                    mwsttyp = vtcapp.evalocl(s)
                    s = "-&gt;reject(mwstsatz=0)-&gt;select((datum&gt;=" + vtcapp.ocldate(von) + ") and (datum&lt;=" + vtcapp.ocldate(bis) + "))"
                    print s
                    leist = rech.eval("leistungen" + s)
                    for l in leist:
                        l.xmwsttyp=mwsttyp

                    spesen = rech.eval("spesen" + s)
                    for l in spesen:
                        l.xmwsttyp=mwsttyp

                    auslagen = rech.eval("auslagen" + s)
                    for l in auslagen:
                        l.xmwsttyp=mwsttyp

                    mwstcode=mwsttyp.code


                    vtcapp.msgbox('Le traitement est terminé.\n\n' + str(len(leist)) + \
                    ' Prestations\n' + str(len(spesen)) + ' Frais\n' + str(len(auslagen)) + \
                    ' Dépenses\nont le nouveau type de TVA ' + mwstcode + '.')
                else:
                     vtcapp.msgbox("Vous n'avez pas sélectionné de type de TVA.\nLe traitement a été interrompu.")

        if (version &lt; 6100000):
            # Versionen vor 6.1, also vor Python Dialogen
            vonDefault = rech.eval('date.firstofmonth.asstring')
            von, bis, comboindex, Abbrechen = ShowVtcformDialog('Neuen MwSt-Typ setzen',vonDefault,'31.12.2017', mwsttypen)
            if not Abbrechen:
                if comboindex &lt;&gt; -1:
                    mwstid = int(mwsttypen[comboindex].eval('boldid'))
                    mwstcode = str(mwsttypen[comboindex].code)
                    rech = argobject

                    if not von:
                        von = '01.01.1900'
                    if not bis:
                        bis = '31.12.2050'

                    s = "Mwsttyp.allinstances-&gt;reject(satz=0)-&gt;select(boldid=" + str(mwstid) + ")-&gt;first"
                    mwsttyp = vtcapp.evalocl(s)
                    s = "-&gt;reject(mwstsatz=0)-&gt;select((datum&gt;='" + von + "'.strtodate) and (datum&lt;='" + bis + "'.strtodate))"

                    leist = rech.eval("leistungen" + s)
                    for l in leist:
                        l.xmwsttyp=mwsttyp

                    spesen = rech.eval("spesen" + s)
                    for l in spesen:
                        l.xmwsttyp=mwsttyp

                    auslagen = rech.eval("auslagen" + s)
                    for l in auslagen:
                        l.xmwsttyp=mwsttyp

                    if mwstcode == '':
                        text = str(mwsttypen[comboindex].bezeichnung)
                    else:
                        text = mwstcode

                    vtcapp.msgbox('Die Verarbeitung ist abgeschlossen.\n\n' + str(len(leist)) + \
                    ' Leistungen\n' + str(len(spesen)) + ' Spesen\n' + str(len(auslagen)) + \
                    ' Auslagen\nhaben den neuen MwSt-Typ ' + text + '.')
                else:
                    vtcapp.msgbox('Sie haben keinen MwSt Typ ausgewählt.\nDie Verarbeitung wurde abgebrochen.')
    else:
        vtcapp.msgbox('Dieses Script kann nur auf einer offenen Rechnung ausgeführt werden.')

def showPythonDialog(dlgDefinition, initValues, version):

    def strptime(date_s):
        """Partial substitute for datetime.datetime.strptime
        due to scripting restrictions."""
        try:
            year_s, month_s, day_s = date_s.split('-')
            year = int(year_s)
            month = int(month_s)
            day = int(day_s)
            return datetime.datetime(year, month, day)
        except:
            raise ValueError('The string %s could not be parsed into a date.' %date_s)

    ok, values = vtcapp.showcustomdialog(dlgDefinition, initValues)

    von = None
    bis = None
    mwstid = None

    if ok:
        if (version &lt; 6100014):
            von = values['DatumVon'][:10]
            bis = values['DatumBis'][:10]

            von = strptime(von).date()
            bis = strptime(bis).date()
        if (version &gt;=6100014):
            von = values['DatumVon'].date()
            bis = values['DatumBis'].date()

        if von.year == 1:
            von = datetime.date(1900,1,1)
        if bis.year == 1:
            bis = datetime.date(2050,12,31)

        mwstid = values['MwstTyp']

    return ok, von, bis, mwstid


def ShowVtcformDialog(titel, von, bis, mwsttypen):
    # mit vtcForms für Versionen vor 6.1
    """Zeigt Dialog mit Monatsauswahl an.
    Standard ist letzter Monat"""

    import vtcforms

    def ValidateForm(sender):
        valid=True
        d1 = ''
        d2 = ''
        try:
            if edt1.Text:
                d1 = vtcapp.strtodate(edt1.Text)
        except:
            valid = False
            vtcapp.msgbox('Das Von-Datum ist ungültig.')
        if valid:
            try:
                if edt2.Text:
                    d2 = vtcapp.strtodate(edt2.Text)
            except:
                valid = False
                vtcapp.msgbox('Das Bis-Datum ist ungültig.')
        if valid:
            if d1 == '' and d2 == '':
                valid = ShowJaNeinDialog('Vertec')

            if d1 &lt;&gt; '' and d2 &lt;&gt; '':
                if d1 &gt; d2:
                    vtcapp.msgbox("Das Von-Datum darf nicht grösser als das Bis-Datum sein.")
                    valid = False
        if valid:
            frm.ModalResult = vtcforms.mrOk

    # create dialog form
    frm=vtcforms.Form(vtcforms.Application)
    frm.BorderStyle=3   # bsDialog
    frm.Caption=titel
    frm.ClientWidth=240
    frm.ClientHeight=150
    btnOK=vtcforms.Button(frm)
    frm.Position=4  # poScreenCenter

    lbl1=vtcforms.Label(frm)
    lbl1.Parent=frm
    lbl1.AutoSize=True
    lbl1.Left=10
    lbl1.Top=39
    lbl1.Caption='Von:'

    edt1=vtcforms.Edit(frm)
    edt1.Parent=frm
    edt1.Left=150
    edt1.Top=35
    edt1.Width=80
    edt1.MaxLength=255
    edt1.Text = von
    edt1.AutoSelect=True

    lbl2=vtcforms.Label(frm)
    lbl2.Parent=frm
    lbl2.AutoSize=True
    lbl2.Left=10
    lbl2.Top=63
    lbl2.Caption='Bis:'

    edt2=vtcforms.Edit(frm)
    edt2.Parent=frm
    edt2.Left=150
    edt2.Top=59
    edt2.Width=80
    edt2.MaxLength=255
    edt2.Text = bis
    edt2.AutoSelect=True

    lbl3=vtcforms.Label(frm)
    lbl3.Parent=frm
    lbl3.AutoSize=True
    lbl3.Left=10
    lbl3.Top=89
    lbl3.Caption='neuer MwSt Typ:'

    lbl4=vtcforms.Label(frm)
    lbl4.Parent=frm
    lbl4.AutoSize=True
    lbl4.Left=10
    lbl4.Top=12
    lbl4.Caption='Betrifft: Leistungen, Spesen und Auslagen.'

    cmb=vtcforms.ComboBox(frm)
    cmb.Parent=frm
    cmb.Left=100
    cmb.Top=85
    cmb.Width=130
    cmb.Style = 2

    for m in mwsttypen:
        cmb.Items.Add(m.code +  ' __ ' + m.bezeichnung)

    btnOK=vtcforms.Button(frm)
    btnOK.Parent=frm
    btnOK.Caption='OK'
    btnOK.Default=True
    btnOK.Top=120
    btnOK.Left=75
    btnOK.OnClick=ValidateForm

    btnCancel=vtcforms.Button(frm)
    btnCancel.Parent=frm
    btnCancel.Caption='Abbrechen'
    btnCancel.Cancel=True
    btnCancel.ModalResult=vtcforms.mrCancel
    btnCancel.Top=120
    btnCancel.Left=155

    # show modal dialog
    if frm.ShowModal() == vtcforms.mrOk:
        return edt1.Text, edt2.Text, cmb.ItemIndex, False
    else:
        return '','', '', True

def ShowJaNeinDialog(titel):
    """Zeigt Dialog Ja / Nein an"""

    # create dialog form
    frm=vtcforms.Form(vtcforms.Application)
    frm.BorderStyle=3   # bsDialog
    frm.Caption=titel
    frm.ClientWidth=325
    frm.ClientHeight=100
    btnOK=vtcforms.Button(frm)
    frm.Position=4  # poScreenCenter

    lbl1=vtcforms.Label(frm)
    lbl1.Parent=frm
    lbl1.AutoSize=True
    lbl1.Left=10
    lbl1.Top=14
    lbl1.Caption='Es ist kein Datum ausgewählt.\nEs werden alle Leistungen, Spesen und Auslagen berücksichtigt.'

    btnOK=vtcforms.Button(frm)
    btnOK.Parent=frm
    btnOK.Caption='OK'
    btnOK.Default=True
    btnOK.Top=65
    btnOK.Left=159
    btnOK.ModalResult=vtcforms.mrOk

    btnCancel=vtcforms.Button(frm)
    btnCancel.Parent=frm
    btnCancel.Caption='Abbrechen'
    btnCancel.Cancel=True
    btnCancel.ModalResult=vtcforms.mrCancel
    btnCancel.Top=65
    btnCancel.Left=239

    # show modal dialog
    if frm.ShowModal() == vtcforms.mrOk:
        return True
    else:
        return False

Main(argobject)</member>
      <member name="EventType">None</member>
      <member name="ObjectScript">true</member>
      <member name="ExtendedRights">false</member>
      <member name="SelectedObjectsScript">false</member>
      <member name="Platform">Python</member>
    </object>
  </objects>
  <settings />
</configset>