
    R*jJ                       d Z ddlZddlZddlZddlZddlZddlmZ ddlmZm	Z	m
Z
 ddlmZmZ ddlZddlmZmZ ddlmZmZmZ 	 ddlZddlmZ dd	lmZmZmZmZm Z m!Z!m"Z"m#Z# dd
l$m%Z%m&Z&m'Z'm(Z(m)Z)  ejT                  ejV                  d        ejX                  e-      Z.de/de0fdZ1d Z2 G d d      Z3y# e$ r dZdZY sw xY w)u   Orchestrator für das EEG-Abrechnungssystem.

Enthält die Klasse Abrechnungssystem sowie globale Hilfsfunktionen
(validate_params, validate_member_row, build_ust_hints).
Die eigentliche Fachlogik liegt in den core/-Modulen.
    N)OrderedDict)datetimedate	timedelta)ListDict)load_workbookWorkbook)FontPatternFill	Alignment)
filedialog)SEX_MALE
SEX_FEMALEDEFAULT_DATERECHNUNG_COLUMNS_AV_KONSTANTENMitgliedvalidate_member_rowbuild_ust_hints)	mask_iban
iban_validvereinsname_to_from_emailmask_name_for_logmask_filename_for_logz)%(asctime)s - %(levelname)s - %(message)s)levelformatibanreturnc                     t        |       S )u3   Prüft die IBAN-Prüfsumme nach ISO 7064 MOD-97-10.)r   r   s    ./var/www/html/eeg-assistent/abrechnung/main.py_iban_validr#   .   s    d    c           
      	   d }g } || j                  d            xs d}dd || j                  d            fdd || j                  d            fdd	 || j                  d	            fd
d || j                  d            ffD ]   \  }}}|r
|j                  || dd       " |dk(  rpdd || j                  d            fdd || j                  d            fdd || j                  d            ffD ]   \  }}}|r
|j                  || dd       "  || j                  d	            }|rM|j                  dd      }|r|d   nd}	t        |	      dk7  s|	j	                         s|j                  ddd       |dk(  r || j                  d            }
|
rt        |
      s|j                  ddd        || j                  d            j                  dd      }|rAt        |      dvs |j                         r|j                         s|j                  ddd        || j                  d            j                  dd      }|r2|j                         rt        |      d kD  r|j                  dd!d       d"D ]l  \  }} || j                  |            j                  d#d$      }|s|j                  || dd       G	 t        |      dk  r|j                  || d%d       n  || j                  d'            }|s|j                  d'd(d       n#	 t        |      dk  r|j                  d'd)d       | j                  d+      }t        |t              r|rd,nd-}n: ||      j                         }|d.v rd,}n|d/v rd-}n|j                  d+d0d       d,} || j                  d1            j                         j                  dd      }|d-k(  r`|s|j                  d1d2d       |S |j!                  d3      r!t        |      d4k(  r|d5d j	                         s|j                  d1d6d       |S |rF|j!                  d3      r!t        |      d4k(  r|d5d j	                         s|j                  d1d6d       |S # t        $ r |j                  || d&d       Y )w xY w# t        $ r |j                  d'd*d       Y w xY w)7u   Prüft die Vereinsparameter (aus Formular oder Parameter.csv).

    Gibt eine Liste von Dicts zurück – je Fehler einen:
      {"field": "<form-feld-id>", "fehler": "<menschliche Meldung>"}
    c                 :    | yt        |       j                         S )N )strstrip)vs    r"   _szvalidate_params.<locals>._s9   s    91v||~r$   abbuchung_modusueberweisungVereinsnamevereinsnameu   StraßevereinsstrasseOrt
vereinsortzZVR-Zahlzvrz fehlt)fieldfehlereigenes_kontoIBAN	sepa_ibanBICsepa_biczCreditor-IDsepa_creditor_idN   r   r'      
vereinsplzz$PLZ muss 4-stellig sein (z. B. 3340)u)   Ungültige IBAN (Prüfsumme stimmt nicht)       u4   Ungültiger BIC (8 oder 11 Zeichen, Großbuchstaben)#   u8   Ungültige Creditor-ID (alphanumerisch, max. 35 Zeichen)))tarif_einspeisungzTarif Einspeisung)tarif_bezugzTarif Bezug,.u    muss größer 0 seinu    ist keine gültige Zahlfaelligkeitu   Fälligkeit fehltu    Fälligkeit muss größer 0 seinu%   Fälligkeit muss eine ganze Zahl seinkleinunternehmerJaNein)r'   jajyesytrue1wahrneinnnofalse0falschz'Kleinunternehmer muss Ja oder Nein sein
uid_nummerz6UID-Nummer fehlt (Pflicht wenn nicht Kleinunternehmer)ATUrB      z.UID-Nummer muss im Format ATU + 8 Ziffern sein)getappendsplitlenisdigitr#   replaceisalnumisupperfloat
ValueErrorint
isinstanceboollowerupper
startswith)paramsr+   errorsr,   labelr4   valortpartsplzr   biccidkeyrawfaellku_rawku_normku_struid_vals                       r"   validate_paramsr}   3   s   
 F$567I>O 
"VZZ-F*GH	)2fjj9I.J+KL	"VZZ-E*FG	"VZZ->*?@	 Huc MMEwf5EFGH /)K6::k3J0KLJ6::j3I0JK.6::>P3Q0RS"
 	LE5#
 E7&9IJK	L VZZ%
&C
		$"eAhRs8q=MML%KM N /)&**[)*D)MMK%PR S J'(00b9CHG+3;;=MMJ%[] ^ ./088bASBMM$6%_a b= 
X
UC!))#s3MMCeWF3CDE	XSzQ%@U7VWX
X vzz-()E9LMN	O5zQ)KM N ZZ*+F&$ $fF!!#EEGBBGMM$6%NP QGL)*002::3CG&MML%]_ ` M $$U+G0Bwqr{GZGZG\MML%UW X M 
""5)c'lb.@WQR[EXEXEZMML%UW X MY  	XMMCeW<T3UVW	X  	OMMM%LN O	Os$   %R'"R6  R32R36SSc            
          e Zd ZdZdefdZd ZdededefdZd	edd
fdZde	eef   fdZ
d Zdej                  de	eef   fdZdefdZdadZdefdZdefdZdedej                  de	eef   dd
fdZdej                  de	eef   fdZd ZdedefdZdeddfdZdedefdZdeded ed!edef
d"Zd#ed$edd
fd%Zdedefd&Z 	 dbded'edd(fd)Z!	 	 dcded*ed'edefd+Z"dedefd,Z#dedd
fd-Z$d. Z%e&d/ed0edd
fd1       Z'e&d2edefd3       Z(e&defd4       Z)e&d5        Z*d6ed7edefd8Z+e&d9ed7edefd:       Z,d6ed7edefd;Z-	 ddd/ed7ed<edefd=Z.d>edd
fd?Z/dedd
fd@Z0defdAZ1de2fdBZ3dadCZ4dedefdDZ5d'edEe6dd
fdFZ7dadGZ8dadHZ9dI Z:dJedd
fdKZ;d'edd
fdLZ<dMedd
fdNZ=e&	 dedOedPedefdQ       Z>dbdedRefdSZ?dfdTedUefdVZ@dWedXedd
fdYZAdZedUefd[ZBdZedUedefd\ZCdgd]edd
fd^ZDdad_ZEdad`ZFy
)hAbrechnungssystemu   Orchestrator für den EEG-Abrechnungsprozess.

    Fachlogik delegiert an core/-Module. Alle öffentlichen Methoden bleiben
    rückwärtskompatibel (gleiche Signaturen wie v1.07a).
    	main_pathc                    || _         | j                         | _        g | _        t	        j
                         | _        | j                  t        t        | j                  d               z   | _	        d| _
        d| _        d| _        d| _        d| _        d| _        d| _        d gdz  | _        d gdz  | _        d gdz  | _        d gdz  | _        g | _        d| _        d| _        d| _        d| _        y )N   Fälligkeit)daysr'   r              )r   load_configconfig
mitgliederr   nowdatum_rechnungr   rg   datum_abbuchungfolder_rechnungenrechnungsnummertotal_gesamterzeugungtotal_gesamtverbrauch   total_restüberschusstotal_erzeugung_tftotal_eigendeckunghourly_eigenverbrauchhourly_autarkiegradhourly_avg_consumptionhourly_avg_generationnighttime_verbrauch_sorted	_ls_msgid	_gs_msgid_ls_ctrlsum_gs_ctrlsum)selfr   s     r"   __init__zAbrechnungssystem.__init__   s    "&&(*,&lln#22YT[[/06
  
 "$ ,/",/"-0",/,/.2Vb[".2Vb[ .2Vb[#.2Vb["02'r$   c                 B   t         j                  j                  | j                  d| j                        | _        t         j                  j                  | j
                  d      | _        | j                  | j
                         | j                  | j                         y)z#Legt Rechnungs- und SEPA-Ordner an.
RechnungenSEPAN)ospathjoinr   perioder   folder_sepacreate_folderr   s    r"   
init_FileszAbrechnungssystem.init_Files   sm    !#NNL$,,"
 77<<(>(>G41124++,r$   	root_pathfilenamer   c                     t        j                  |      D ],  \  }}}||v st         j                  j                  ||      c S  y)uP   Durchsucht rekursiv alle Unterordner nach filename. Gibt Pfad oder None zurück.N)r   walkr   r   )r   r   r   rootdirsfiless         r"   find_file_in_subfoldersz)Abrechnungssystem.find_file_in_subfolders   sC    !#!3 	4D$5 ww||D(33	4 r$   folder_nameNc                    	 t         j                  j                  |      }t         j                  j                  |      st	        d|       t        j
                  |d       t         j                  j                  |      st        d|       t        j                  |t         j                        st        d|       t        j                  d|        y
# t        t        t        t        f$ r.}t        j                  d| d       t        d	       Y d
}~y
d
}~wt        $ r.}t        j                  d| d       t        d	       Y d
}~y
d
}~ww xY w)z+Erstellt einen Ordner mit Fehlerbehandlung.u&   Übergeordneter Pfad existiert nicht: Texist_okzKonnte Ordner nicht erstellen: u!   Keine Schreibrechte für Ordner: zOrdner erstellt: z#Fehler beim Erstellen des Ordners:     – ABBRUCHr<   Nz*Unbekannter Fehler beim Ordner erstellen: )r   r   dirnameexistsFileNotFoundErrormakedirsOSErroraccessW_OKPermissionErrorloggerinforf   errorexit	Exception)r   r   
parent_dires       r"   r   zAbrechnungssystem.create_folder   s   	5J77>>*-'<ZLI  KKd377>>+. ?}MNN99["''2%(I+&WXXKK+K=9:!?GZH 	LL>qcNOGG 	LLEaSUVGG	s$   CC E6$DE+$EEc           
      $	    i }dt         dt        dt         f fd}t        j                  j	                   j
                  dd      }	 t        j                  |ddg d	
      }||d   j                         |d   j                  t              j                  j                         dk7  z  |d   j                  t              j                  j                         j                  j                         dk7  z     }|j                  t        t        |d   |d                      dg di} ||d|       t        j                  j	                   j
                  dd      }	 t%        |d      5 }t'        j(                  |      }	ddd       |j                  	j+                         D 
ci c]  \  }
}|
|dn
t        |       c}}
       |j-                  dd       |j-                  dd       |j-                  dd       |j-                  dd       |j-                  dd       |j-                  d d!       |j-                  d"d       |j-                  d#d       t        |j/                  dd            j                         j                         }|d$v rd|d<   n1|d%v rd&|d<   n't        j!                  d'|d    d(       t#        d       |d   d&k(  rt        |j/                  dd            j                         j1                         j3                  d)d      }|s t        j!                  d*       t#        d       |j5                  d+      r!t7        |      d,k(  r|d-d j9                         s$t        j!                  d.| d(       t#        d       ||d<   d/d0 fd1d2 fd3d4 fgd5g|j/                  d6d7      d8v rg n	d9d: fd;d< fg|j/                  d6d7      d8v rg nd=d> fgg g d?d@} ||d|       t        j;                  dA       |S # t        $ r/}t        j!                  d| d       t#        d       Y d}~d}~ww xY w# 1 sw Y   xY wc c}}
w # t        $ r/}t        j!                  d| d       t#        d       Y d}~d}~ww xY w)Bu0   Lädt und validiert Config.csv + Parameter.json.entriessourcerequired_groupsc           
         |j                         D ]2  \  }}|dk(  ri|D ]c  \  }}|| vr't        j                  d| d| d       t        d       	  || |         s't        j                  d| d| d       t        d       e u|d	k(  r|D ]  }|| vr't        j                  d| d| d       t        d       t        j                  j                  j                  | |         }t        j                  j                  |      }t        j                  j                  |      rj                  j                  |      }	|	rt        j                  d
|	 d| d       t        j                  d| d| d       t        d        }|dk(  rj|D ]c  \  }}|| vr't        j                  d| d| d       t        d        || |         r=t        j                  d| d| d       t        d       e |dv r|D ]  }
t        |
t              r|
n|
df\  }}|| vr't        j                  d| d| d       t        d       t!        | |         j#                         s't        j                  d| d| d       t        d       |s || |         rt        j                  d| d| d       t        d        |dk(  s|D ]q  }|| vr't        j                  d| d| d       t        d       t!        | |         j#                         rKt        j                  d| d| d       t        d       s 5 y# t        t
        f$ r+ t        j                  d| d| d       t        d       Y bw xY w)u-   Validiert alle Einträge einer Config-Quelle.	numerischzFehlender Eintrag in : r   r<   u   Ungültiger Wert für z in u!   : Keine gültige Zahl – ABBRUCH
dateipfadez2Datei nicht im erwarteten Pfad, aber gefunden in: z (Key: )zDatei nicht gefunden: u   ) – ABBRUCHiban_bicu   Ungültige )creditor_idemailbooleanNzLeerer Wert in u    für Key: freitext)itemsr   r   r   rf   AttributeErrorr   r   r   r   basenamer   r   warningrh   tupler(   r)   )r   r   r   
group_namekeysrv   	validatorexpected_pathr   
found_pathentryr   s              r"   validate_config_entriesz>Abrechnungssystem.load_config.<locals>.validate_config_entries   s   $3$9$9$; G$ 
D,*. $Yg-"LL+@3%|)\] G
$#,WS\#: &&<SEfX\$Z!" !%Q$  </# (g-"LL+@3%|)\] G(*T^^WS\(R#%77#3#3M#B!ww~~m<)-)E)E $*J  * &&X'1l'#a%A!"
 !'&<XJgcUR_$`!" !%Q'((  :-*. $Yg-"LL+@3%|)\] G(6"LL;se4x|)TU G$  #FF!% $2<UE2JQVX\P]Yg-"LL+@3%|)\] G"73<0668"LL"1&SE V !G$Yws|-D"LL"8T& V !G$  :-# $g-"LL+@3%|)\] G"73<0668"LL"1&SE V !G$G$ !+N; $"LL"8T&Ij k !G	$s   2M		6NNConfigz
Config.csv;N)BezeichnungKeywortSuchwort)sepheadernamesr   r'   keywortr   z"Fehler beim Lesen von Config.csv: r   r<   r   )TB_MitgliedMitglied_IDMitglied_VornameMitglied_NachnameMitglied_SexMitglied_AdresseMitglied_PLZMitglied_OrtMitglied_MailMitglied_IBANMitglied_BICMitglied_FirmennameMitglied_CONSUMPTIONMitglied_GENERATIONEDA_direction_CEDA_direction_GEDA_EigendeckungEDA_ErzeugungEDA_OverflowEDA_GesamterzeugungEDA_GesamtverbrauchTB_Rechnungsnummer
TB_VorlagezParameter.jsonzutf-8)encodingz&Fehler beim Lesen der Parameter.json: KleinunternehmerrJ   
UID_NummerMitglied_Steuersatz
SteuersatzMitglied_UIDMitglied_EintrittsdatumMitglied seitRC_Kostentraegerr   Logo_FilenameAccent_Color)rL   rM   rN   rO   rP   rQ   rR   rS   rK   u)   Ungültiger Wert für Kleinunternehmer: 'u   ' – ABBRUCHr?   u.   UID-Nummer fehlt in Parameter.json – ABBRUCHr[   rB   r\   u   Ungültige UID-Nummer: 'Tarif_Bezugc                 >    t        | j                  dd            dkD  S NrF   rG   r   re   rb   xs    r"   <lambda>z/Abrechnungssystem.load_config.<locals>.<lambda>      qyyc7J1Ka1O r$   Tarif_Einspeisungc                 >    t        | j                  dd            dkD  S r  r  r  s    r"   r  z/Abrechnungssystem.load_config.<locals>.<lambda>  r  r$   r   c                     t        |       dkD  S )Nr   )rg   r  s    r"   r  z/Abrechnungssystem.load_config.<locals>.<lambda>  s    #a&1* r$   File_MitgliederAbbuchung_Modusr-   )abrechnungsvereinr-   	SEPA_IBANc                     t        | j                  dd            dk\  xr  | j                  dd      j                         S )Nr?   r'      )r`   rb   rc   r  s    r"   r  z/Abrechnungssystem.load_config.<locals>.<lambda>  s;    C		#r0B,Cr,I -M01		#r0B0J0J0L r$   SEPA_BICc                 d    t        |       dv xr" | j                         xr | j                         S )Nr@   )r`   rc   rd   r  s    r"   r  z/Abrechnungssystem.load_config.<locals>.<lambda>  s-    CFg,= -<!))+ -<01		 r$   SEPA_Creditor_IDc                 B    | j                         xr t        |       dk  S )NrC   )rc   r`   r  s    r"   r  z/Abrechnungssystem.load_config.<locals>.<lambda>  s    QYY[5QSVr\ r$   )r.   Vereinsstrasse
VereinsortFile_Rechnungsnummer)r   r   r   r   r   r   u/   Konfiguration erfolgreich geladen und geprüft.)dictr(   r   r   r   r   pdread_csvnotnaastyper)   rj   updatezipr   r   r   r   openjsonloadr   
setdefaultr]   rk   rb   rl   r`   ra   r   )r   r   r   config_path	config_dfr   required_keys_configparameter_path_pf_param_datakr*   ry   r|   required_keys_parameters   `              r"   r   zAbrechnungssystem.load_config   s   I	$T I	$3 I	$QU I	$V ggll4>>8\J	T<I ")$**,Y'..s377==?2EGY'..s377==?CCIIKyXZI
 MM$s9Y#7:9NOPQ  
 
 	 6JKdnnh@PQ	nw7 -3"iin-MM>I>O>O>QRda19R#a&0R 	,d3,+/>.,73_E,j9/2.."- VZZ 2D9:@@BHHJAA)-F%&BB)/F%&LL;FCU<V;WWde G$%/&**\267==?EEGOOPSUWXGMNQ&&u-#g,"2D++-7yNOQ#*F<  'OP$'OP(<=
 -- ::/@Dii  ! #M N #< = ::/@Dii )+QRS/#
6 	 (8:QREFw  	LL=aSMNGG	&- - S 	LLA!LQRGG	sU   CP	 Q ,Q&Q (Q
Q 		Q$P<<QQ	Q 	R $R

Rc                    t         j                  j                  | j                  | j                  d         }t        j                  || j                  d         }|j                         D ]  \  }}t        j                  || j                  d            s&t        j                  || j                  d            sR| j                  || j                        }|r#t        j                  | d       t        d       |j                  | j                  d         }t        j                  |      sd	n
t        |      }|j                  | j                  d
         }t        j                  |      sd	n
t        |      }| d| j                         xs d}| j                  j                  dd      }	|j                  |	      }
	 t        j                  |
      rIt        |
      j                         d	k7  r-t!        t#        t        |
      j%                  dd                  nd}|dvrd}| j                  j                  dd      }|j                  |      }d	}t        j                  |      rPt        |      j                         r7t        |      j                         j+                         j%                  dd	      }|j                  | j                  d         }|.t        j                  |      rt        |      j                         s|nt        |      j                         }| j                  j                  dd      }|j                  |      }t,        }|t        j                  |      r	 t/        |t0        t
        j2                  f      r4t        j2                  |      j5                         j%                  d      }n-t1        j6                  t        |      j                         d      }| j:                  j=                  t?        t        t!        t#        t        || j                  d                              ||| j                  d      r7t        || j                  d            j                         jA                         nd	|| j                  d       || j                  d!      t        t!        t#        t        || j                  d"                              || j                  d#      || j                  d$      || j                  d%      || j                  d      || j                  d      ||||&              t        jC                  tE        | j:                         d'       y# t&        t(        f$ r d}Y fw xY w# t&        t(        f$ r  t        j9                  d| d| d       Y w xY w)(u)   Lädt die Mitglieder aus der Excel-Datei.r  r   
sheet_namer   r   r   r<   r   r'   r   r?   	Unbekanntr  r  rF   rG   r   )r         r  r  r   Nr  r  tzinfo%d.%m.%Yu   Ungültiges Eintrittsdatum 'u   ' für u    – ignoriert.r   r   r   r   r   r   r   r   )IDNameSexMailStrassePLZr1   r7   r9   ZP_ConsumptionZP_GenerationName4Rechnungr  UIDEintrittsdatumz Mitglieder geladen.)#r   r   r   r   r   r#  
read_exceliterrowsr%  validate_member_datar   r   r   r]   r(   r)   rg   re   rb   rf   	TypeErrorrk   r   rh   r   	Timestampto_pydatetimestrptimer   r   r^   r   rj   r   r`   )r   
excel_pathdf_row	error_msgvornamenachnamename
steuer_col
steuer_rawsteuersatz_valuid_coluid_rawmitglied_uid_firmenname_raw_name4rechnung	_seit_col	_seit_raw_eintrittsdatums                       r"   init_mitgliederz!Abrechnungssystem.init_mitglieder  s   WW\\$..$++>O2PQ
]]:$++m2LMkkm I	FAsHHS-C!DEFxxDKK0E$F GH11#t{{CI	{,78Qwwt{{+=>?G!#'!2rGGwwt{{+>?@H!#(!3rXH!!H:.446E+D;;??+@,OJ77:.J# xx
+J0E0E0G20M c*o55c3?@A  [0!"++//.,GG'''*GLxx S\%7%7%9"7|11399;CCCL!ggdkk2G&HIO $+288O3L/557  )//1	  (A?SI	*I*O$))<k!)h-EF*,,,y*A*O*O*Q*Y*Yae*Y*f*2*;*;C	N<P<P<RT^*_ OO""8s5S])C%D!EFGHDKK78 T[[89:@@BHHJ>@_56DKK(:;<E#c$++n*E&F"GHIJN34_56N34"4;;/E#FG!$++.C"DE,) .!$ qI	T 	s4??+,,@ABe 	* #!"#: #I. kNN%A)GTXSYYh#ijks&   A U84BV8VV+V?>V?rS  r   c                     	 |j                  |d         }	 t        j                  |      rt        t	        |            nd}|j                  dd      }|j                  dd      }t        |j                  |d         |j                  |d         |j                  |d	         |j                  |d
         |j                  |d         |j                  |d         ||j                  |d         |j                  |d         |j                  |d         |j                  |      |j                  |            S # t
        t        f$ r& t        j                  |      rt        |      nd}Y /w xY w# t        $ r}d| cY d}~S d}~ww xY w)uW   Prüft eine Mitgliederzeile gegen die Config-Spalten. Delegiert an validate_member_row.r   r'   r  r  r  r  r   r   r   r   r   r   r   r   r   )	member_idrU  rV  mailr   rt   rs   rq   strassesex
steuersatzuidu-   Fehler beim Prüfen der Daten für Mitglied: N)	r]   r#  r%  r(   rg   rf   rL  r   r   )r   rS  r   plz_rawrs   rX  r[  r   s           r"   rK  z&Abrechnungssystem.validate_member_data  sq   	Gggf^45G@+-88G+<c#g,'"  $9<HJNLAG& WWVM%:; WWV,>%?@ WWV,?%@A WWVO%<= WWVO%<= WWVN%;<  WWVN%;< WWV,>%?@ WWVN%;< WWZ0 WWW-  	* @&(hhw&7c'lR@(  	GB1#FF	GsA   E5 +D= C:E5 =1E2.E5 1E22E5 5	F>FFFc           	         g }	 t         j                  j                  | j                  | j                  d         }t         j                  j                  |      s(ddddt         j                  j                  |       dgS 	 t        j                  || j                  d         }|j                         D ]$  \  }}	 t        j                  || j                  d            }t        j                  || j                  d            }|s|sW| j                  || j                        }
|
sv	 |j!                  | j                  d   d      xs d}|j!                  | j                  d   d      xs d}| d| j#                         xs d}	 t%        |j!                  | j                  d   d      xs d      }|j                  t        |      dz   |||
d       ' |S # t
        $ r dddddgcY S w xY w# t        $ r}dddd	| dgcY d
}~S d
}~ww xY w# t
        $ r0}	|j                  t        |      dz   ddd|	 d       Y d
}	~	d
}	~	ww xY w# t        $ r d}Y w xY w# t        $ r d}Y w xY w)uM   Prüft die komplette Mitgliederliste und gibt ALLE gefundenen Fehler zurück.r  r   r'   z*File_Mitglieder fehlt in der Konfiguration)zeileidrW  r5   z Mitgliederdatei nicht gefunden: r   r6  z-Mitgliederdatei konnte nicht gelesen werden: Nr   r      zSpalte fehlt: r   r   r?   r8  r   )r   r   r   r   r   KeyErrorr   r   r#  rI  r   rJ  r%  r^   rg   rK  r]   r)   r(   )r   rn   rP  rQ  r   idxrS  has_chas_gkerT  rU  rV  rW  re  s                  r"   validate_all_membersz&Abrechnungssystem.validate_all_members   s   	NdnndkkBS6TUJ
 ww~~j)r2!A"''BRBRS]B^A_`b c c	Uzdkk-6PQB
  	HCT[[1G%H!IJT[[1F%G!HI
 U11#t{{CI'"wwt{{3E'FKQrG"wwt{{3F'GLRPRH")!H:6<<>M+D# #CGGDKK,F$K$Qr RI !#hl'"'	 /	: W  	Nr2KM N N	N  	Ur2!NqcRT U U	U  C1B+9")>@ A ! '&D' ! # "I#sm   7G! $G8 ?A
H.AI,I&!G54G58	H
HHH	I"%III#"I#&I43I4c                 &   t               }| j                  D ]  }|j                  r3t        |j                        j	                  dd      j                         nd}|j                  j                         j                         |f}||vrg ||<   ||   j                  |        d}g }|j                         D ]  \  }}t        |      dk(  r|j                  |d          *|d   }|dd D ]  }	|xj                  |	j                  z  c_        |xj                  |	j                  z  c_        t        j                  |j                         r0t        j                  |	j                         s|	j                   |_        t        j                  |j"                        r0t        j                  |	j"                        s|	j"                  |_        dD ]I  }
t%        |	|
      }t%        ||
      }|s|t&        k7  s(t)        ||
|t&        k(  r|nt+        ||             K dD ]I  }t%        |	|      }t%        ||      }|s|t&        k7  s(t)        |||t&        k(  r|nt-        ||             K |dz  }t.        j1                  d|	j                   d	|	j2                   d
|j                   d	|j2                   d	        |j                  |        |r;t.        j1                  dt        | j                         dt        |       d| d       || _        y)z?Fasst Mitglieder mit gleichem Namen UND gleicher IBAN zusammen.r?   r'   r   r<   N)Start_CStart_G)Ende_CEnde_GzZusammenfassung: z (ID: u   ) → r   zMitglieder zusammengefasst: u    → z (z zusammengefasst))r   r   r7   r(   rb   rk   r?  r)   rj   r^   r   r`   Consumption
Generationr#  isnarD  rE  getattrr   setattrminmaxr   r   r>  )r   groupsm
iban_cleanrv   merged_countnew_mitgliedermembersprimaryother
start_attr	other_valprim_valend_attrs                 r"   _merge_duplicate_membersz*Abrechnungssystem._merge_duplicate_membersR  s   )m 	"AABQVV,,S"5;;=RJ66<<>''):6C&  s3Kq!	" )+"LLN 	+LC7|q %%gaj1ajG  ##u'8'88#""u'7'77"7771122775CWCW;X-2-A-AG*777001"''%BUBU:V,1,?,?G)"8 ?J 'z :I ' <H Y,%>-5-E	%(9%=?	? !5 ?H 'x 8I ' :H Y,%>-5-E	%(9%=?	? !'

|6%(( D"<<.wzzl!=-4 !!'*?	+B KK.s4??/C.DE~&'r,7HJ )r$   report_pathc                      ddl m}  || |      S )z3Liest den EDA-Report. Delegiert an core.eda_reader.r   )read_eda_report)core.eda_readerr  )r   r  r  s      r"   r  z!Abrechnungssystem.read_eda_report  s    3t[11r$   c                     t        d |D              }t        d |D              }|dk(  rt        j                  d       yt        ||z
        |z  dz  }|dkD  rt        j                  d|d	d
       yy)uF   Prüft ob Consumption und Generation im Toleranzbereich liegen (±1%).c              3   4   K   | ]  }|j                     y wNr{  .0r  s     r"   	<genexpr>zAAbrechnungssystem.check_consumption_generation.<locals>.<genexpr>  s     8amm8   c              3   4   K   | ]  }|j                     y wr  r|  r  s     r"   r  zAAbrechnungssystem.check_consumption_generation.<locals>.<genexpr>  s     8all8r  r   u3   Generation ist 0 – Division durch Null vermieden!Fd         ?z#Abweichung Consumption/Generation: .2fu   % (max ±1%)T)sumr   r   abs)r   r   total_Ctotal_Gdeviation_percents        r"   check_consumption_generationz.Abrechnungssystem.check_consumption_generation  s    8Z888Z88a<LLNO' 12W<sBs"LL56G5LLY r$   mitgliedc                 L   ||d      |d   k(  r|xj                   ||d      z  c_         |j                  t        k7  rt        |j                  ||d            n||d      |_        t	        |j
                  ||d            |_        d	|_	        y
||d      |d   k(  r|xj                  ||d      ||d      z
  z  c_        |j                  t        k7  rt        |j                  ||d            n||d      |_        t	        |j                  ||d            |_        d	|_	        y
)zMAktualisiert Verbrauchs-/Erzeugungsdaten eines Mitglieds aus einer EDA-Zeile.EDA_directionr   r   EDA_time_fromEDA_time_tor   r   r   TN)
r{  rw  r   r  r  ry  r|  rx  rz  	DataCheck)r   r  rS  r   s       r"   update_member_from_eda_rowz,Abrechnungssystem.update_member_from_eda_row  sO    vo&'62C+DD  C/A(B$CC  ##|3 H$$c&*A&BC01 
 "(//3vm7L3MNHO " ()V4E-FFF?+,s6.3I/JJ
 ##|3 H$$c&*A&BC01 
 "(//3vm7L3MNHO!r$   c                    	 t        ||d            }|r|j                         sy||d      }||d   |d   fvrd| d| S ||d      }||d	      }t        j                  |      st        j                  |      rd
| S ||d      }||d      }||d      }	t	        d |||	fD              rd| S y# t
        $ r}
d|
 cY d}
~
S d}
~
ww xY w)z"Validiert eine einzelne EDA-Zeile.EDA_ZPu(   Zählpunkt (ZP) fehlt oder ist ungültigr  r   r   u   Ungültige Richtung 'u   ' für Zählpunkt r  r  u'   Ungültige Zeitstempel für Zählpunkt r   r   r   c              3   F   K   | ]  }t        j                  |        y wr  )r#  r}  )r  rp   s     r"   r  z5Abrechnungssystem.validate_eda_row.<locals>.<genexpr>  s     OC2773<Os   !u*   Fehlende numerische Werte für Zählpunkt Nu#   Fehler beim Prüfen der EDA-Daten: )r(   r)   r#  r}  anyr   )r   rS  r   zp	direction	time_fromtime_toeigendeckung	erzeugungoverflowr   s              r"   validate_eda_rowz"Abrechnungssystem.validate_eda_row  s   	=S)*+BRXXZAF?34I(9!:FCT<U VV.yk9KB4PPF?34IF=12Gwwy!RWWW%5@EEv&89:Lvo67Ivn56HOL)X+NOOCB4HH 	=8<<	=s.   #B4 B4 >B4 1B4 4	C=CCCc           	         t        | j                  d   j                  dd            }t        | j                  d   j                  dd            }t        | j                  j	                  dd            j                         j                         dk(  }| j                  j	                  dd	      j                         }| j                  D ]R  }	 |r|d	k(  r|j                  d
k(  r	|dz  dz  }n|}t        |j                  |z  |j                  |z  z
  d      |_        T t        j'                  d       y# t        $ rD}t        j                  dt!        |j"                         d| d       t%        d       Y d}~d}~ww xY w)u@   Berechnet die Kosten (Rechnung/Gutschrift) für alle Mitglieder.r
  rF   rG   r  r   rJ   rL   r  r   r:        ro  u%   Fehler bei der Kostenberechnung für r   r   r<   Nu&   Kosten für alle Mitglieder berechnet.)re   r   rb   r(   r]   r)   rj   r   r  roundr{  r|  Kostenr   r   r   r   r?  r   r   )r   rE   rD   rI   rc_kostentraegerr  tarif_einspeisung_effr   s           r"   calculate_kostenz"Abrechnungssystem.calculate_kosten  si   !$++m"<"D"DS#"NO!$++.A"B"J"J3PS"TU0BD IJPPRXXZ^bb KKOO,>
KQQS 	H$)9Z)G$//25,=,AA,E),=)"'((;6)),AAB#	" 	<=  ;<Mhmm<\;]]_`a_bbno Q	s   AD66	F?:E>>Frechnungsnummer_pathc                     ddl m}  ||      S )uX   Legt Kassabuch an (falls nötig) und gibt die letzte Rechnungsnummer des Jahres zurück.r   )init_kassabuch)core.kassabuchr  )r   r  r  s      r"   _generate_rechnungsnummerz+Abrechnungssystem._generate_rechnungsnummer  s    1233r$   z
int | Nonec           	         t         j                  j                  | j                  d| j                  d         }| j                  |      }|sy| j                  j                  d| j                  j                  dd            j                         j                         }|dk(  ro|j                  dkD  rdnd	}| j                  j                  d
d      j                         }| d| j                   d| d|j                   d|j                   	dd }nt        | |j                  dkD  rdndd      }| j                  ||||      S )uM   Vergabe der Rechnungsnummer und Kassabuch-Eintrag. Gibt Zeilennummer zurück.r   r!  Nr  r,   r-   r   RGGSr.   r'    | r?      r   r   )r   r   r   r   r   _get_rechnung_descriptionr]   r)   rj   r  r   Rechnungsnummerr?  r~  _update_rechnungsnummern_datei)r   r  rn_pathdescriptionr,   doc_typr/   buchungstexts           r"   handle_rechnungsnummerz(Abrechnungssystem.handle_rechnungsnummer  s%   ggll4>><McAde44X>++//t{{/@.Q

%'%%' 	 n,#+??Q#64DG;;??="=CCEK-s4<<.)1X556c(--JsL
 #X__q%8kk2L 227HkS_``r$   c                    |j                   j                         t        j                         k7  r|j                   j                         nd}|j                  j                         t        j                         k7  r|j                  j                         nd}|j                  j                         t        j                         k7  r|j                  j                         nd}|j
                  j                         t        j                         k7  r|j
                  j                         nd}|r?|r=|r;|r9t        ||      j                  d       dt        ||      j                  d       S |r'|r%|j                  d       d|j                  d       S |r'|r%|j                  d       d|j                  d       S y)u>   Erstellt die Beschreibungszeile (Zeitraum) für das Kassabuch.Nr=  z bis r'   )rw  r   r   rx  ry  rz  r  strftime)r   r  start_cstart_gende_cende_gs         r"   r  z+Abrechnungssystem._get_rechnung_description  st   -5-=-=-B-B-DHYHYH[-[(""'')ae-5-=-=-B-B-DHYHYH[-[(""'')ae-5__-A-A-CHYHYH[-[(//&&(ae-5__-A-A-CHYHYH[-[(//&&(aev'f7G,55jAB%66*33J?@B C&&z2359T8UVV&&z2359T8UVVr$   r   r  msgidc           
      ~    ddl m}  |||||| j                  | j                  | j                  | j
                        S )z4Delegiert Kassabuch-Zeileneintrag an core.kassabuch.r   )update_kassabuch)r   r  r  r  r   r   r   r   )r  r  r   r   r   r   )r   r   r  r  r  r  s         r"   r  z0Abrechnungssystem._update_rechnungsnummern_datei  sB     	4#;;.. 00"44	
 		
r$   ls_rowsgs_rowsc           
         ddl m} t        j                  j	                  | j
                  d| j                  d         } ||||| j                  | j                  | j                  | j                  | j                         y)z3Delegiert Kassabuch-Sammelzeilen an core.kassabuch.r   )write_kassabuch_batch_summaryr   r!  )r   r  r  ls_msgidgs_msgid
ls_ctrlsum
gs_ctrlsumr   N)r  r  r   r   r   r   r   r   r   r   r   r   )r   r  r  r  r  s        r"   _write_kassabuch_batch_summaryz0Abrechnungssystem._write_kassabuch_batch_summary$  sc    @'',,t~~|T[[I_=`a%^^^^'''' 00		
r$   c           	         t        | j                  j                  dd            j                         j	                         dk(  }| j                  j                  dd      }|j
                  dkD  }|j                  dkD  }t        |||j                  ||      \  }}t        t        | j                  d         j                  d	d
            }t        t        | j                  d         j                  d	d
            }	|dj                  d
d	      }
|	dj                  d
d	      }| j                  j                  dd      j                         }d}d}|r>|dk(  r9|r7|j                  dk(  r(|j                  |	z  dz  }|dj                  d
d	      }d}d}d}d}|rq|j                  dk(  rb|	dz  }|j                  |	z  dz  }|j                  |z  }|dj                  d
d	      }|dj                  d
d	      }|dj                  d
d	      }d}d}d}|sd|rb|dz  }|j
                  |z  dz  }|j
                  |z  }|dj                  d
d	      }|dj                  d
d	      }|dj                  d
d	      }|rv|j
                  |z  dj                  d
d	      }|j
                  dj                  d
d	      }|j                  j                  d      }|j                  j                  d      }ndd}d}|j                  t        k7  r|j                  j                  d      nd}|j                   t        k7  r|j                   j                  d      nd}|rxd|j                  |	z  dj                  d
d	      } |j                  dj                  d
d	      }!|j                  j                  d      }"|j                   j                  d      }#ndd} d}!|j                  t        k7  r|j                  j                  d      nd}"|j                  t        k7  r|j                  j                  d      nd}#|j"                  t$        k(  rd}$n|j"                  t&        k(  rd}$nd}$|j(                  r.t+        j,                  |j(                        r|j(                  dd nd}%|j.                  r.t+        j,                  |j.                        r|j.                  dd nd}&|j0                  dk  }'|'rd nd!}(|j0                  dj                  d
d	      })d"|j2                   }*i d#| j                  d$   d%| j                  d&   d'| j                  d(   d)dd*|$d+|j4                  d,|j6                  r|j6                  n|j4                  d-|j8                  d.|j:                  d/|j<                  d0| j>                  j                  d      d1| j@                  j                  d      d2|jB                  d3tE        |jF                        d4|%d5|&d6|i d7|d8|d9|
d:|d;|"d<|#d=|!d>|d?| d@|)dA|dB|dC|(dD|'dE|*dF|jH                  xs dj                         dG||||||||dHS )Iu9   Baut das Kontext-Dictionary für DOCX- und PDF-Templates.r   rJ   rL   r  r'   r   )rI   
verein_uidmitglied_steuersatz	has_bezughas_einspeisungr
  rF   rG   r  r  r  r   Nr:  r  20r9  gGz?g81s?.4fg333333?gVUUUUU?r=  z0,00-LieberLiebezLiebe/ri
GUTSCHRIFTRECHNUNGzEEG-r/   r.   r0   r  r2   r   logoanrederW  	anschriftrg  rs   rq   rechnungsdatumfaelligkeitsdatumr   kontonummerzp_consumptionzp_generationconsumption_vonconsumption_bisconsumptionrE   kosten_consumptiongeneration_vongeneration_bis
generationrD   kosten_generationgesamtkostenust_hint_bezugust_hint_einspeisungr  is_gutschrift
mandat_refr]  rc_mwst_betrag)rc_mwst_satzlandwirt_mwst_betraglandwirt_netto_tariflandwirt_netto_betragbezug_mwst_betragbezug_netto_tarifbezug_netto_betrag)%r(   r   r]   r)   rj   r{  r|  r   r  re   rb   rw  r  ry  rx  r   rz  r@  r   r   rD  r#  r%  rE  r  r>  r?  rF  rB  rC  r1   r   r   r  r   r7   rG  )+r   r  kleinuntr  r  r  r  r  tarif_b_numtarif_e_numtarif_bezug_strtarif_einspeisung_strr  rc_mwst_betrag_strrc_mwst_satz_str_rc_mwstlandwirt_mwst_betrag_strlandwirt_netto_tarif_strlandwirt_netto_betrag_str_lw_netto_tarif_lw_mwst_lw_netto_betragbezug_mwst_betrag_strbezug_netto_tarif_strbezug_netto_betrag_str_b_netto_tarif_b_mwst_b_netto_betragkosten_cconsumption_strcons_voncons_biskosten_ggeneration_strgen_vongen_bisr  zp_czp_gr  r  gesamtr  s+                                              r"   _build_docx_contextz%Abrechnungssystem._build_docx_context5  sp   T[[__-?FGMMOUUW[__r:
!--1	"--1/>%! ( 3 3+0
,, CM :;CCCMNC,? @AII#sST#.s"3 < <S# F#.s"3 < <S# F![[__-?LRRT!!)Z7#(;(;r(A!)!4!4{!BQ!FH$,S>!:!:3!D!%$( $( $(!x22b8(3d(:O(0(;(;k(I[(YH(0(;(;o(M+3C.(A(A#s(K$+:3*?(H(Hc(R$+;C*@(I(I#s(S%!%!%!%I%03%6N%-%9%9K%G9%UG%-%9%9N%JO(/}%=%=c3%G!(6s';%D%DS#%N!(7'<%E%Ec3%O"!)!5!5!CC HQQRUWZ[H!)!5!5c :CCCMO''00<H//
;H$H$O#++|; !((11*=AC  $??l: !00<@B   !4!4{!B3 GHPPQTVYZH ( 3 3C8AA#sKN&&//
;Goo..z:G#H#N"**l:  ''00<@B  #//\9  //
;?A  <<8#F\\Z'FF **rxx8O8O/P ''-VY 	 ))bhhx7M7M.N &&st,TW 	 !!+(5:#??3/88cBx{{m,
*
$++m"<*
$++.>"?*
 $++l";*
 "	*

 &*
 (--*
 H<R<R("8"8X`XeXe*
 ("2"2*
 (,,*
 (,,*
 $"5"5">">z"J*
  $"6"6"?"?
"K*
 (":":*
 )HMM":*
 $*
  $!*
" (#*
$ (%*
& /'*
( /)*
* !(+*
, '-*
. '/*
0 .1*
2  "73*
4  (5*
6 &7*
8 .9*
: #$8;*
< '=*
> -?*
@ *A*
B x||'9r&@&@&BC*
D &8E*
F '7&>&>&?&;&;&<S*
 *	
r$   output_pathz
str | Nonec                 "    ddl m}  || ||      S )zFRendert Rechnung als PDF via ReportLab. Delegiert an core.invoice_pdf.r   )render_invoice_pdf_html)core.invoice_pdfr0  )r   r  r.  r0  s       r"   r0  z)Abrechnungssystem.render_invoice_pdf_html  s     	=&tX{CCr$   template_pathc                 $    ddl m}  || |||      S )zFRendert Rechnung als DOCX via docxtpl. Delegiert an core.invoice_docx.r   )render_invoice_docx)core.invoice_docxr4  )r   r  r2  r.  r4  s        r"   r4  z%Abrechnungssystem.render_invoice_docx  s     	:"4=+NNr$   c                      ddl m}  || |      S )u<   Füllt Legacy-Excel-Vorlage. Delegiert an core.invoice_docx.r   )fill_template)r5  r7  )r   r  r7  s      r"   r7  zAbrechnungssystem.fill_template  s    3T8,,r$   c                 d    ddl m}  |||| j                  | j                  | j                         y)zGErsetzt [Platzhalter] in Excel-Vorlage. Delegiert an core.invoice_docx.r   )_replace_placeholdersN)r5  r9  r   r   r   )r   wsr  r9  s       r"   r9  z'Abrechnungssystem._replace_placeholders  s)    ;b(DKK"1143G3G	Ir$   c                      ddl m}  |||       S )u?   Erstellt InlineImage für Logo. Delegiert an core.invoice_docx.r   )_build_logo_image)r5  r<  )r   docr<  s      r"   r<  z#Abrechnungssystem._build_logo_image  s    7 d++r$   	docx_path	hex_colorc                 "    ddl m}  || |       y)z:Setzt Akzentfarbe im DOCX. Delegiert an core.invoice_docx.r   )_apply_accent_colorN)r5  rA  )r>  r?  rA  s      r"   rA  z%Abrechnungssystem._apply_accent_color  s     	:Iy1r$   r   c                     t        |       S )u4   Maskiert IBAN für Anzeige. Delegiert an core.utils.)r   r!   s    r"   
_mask_ibanzAbrechnungssystem._mask_iban  s     r$   c                     ddl } | j                  g dddd      }d|j                  v ryt        j	                  d       | j                  g d	dd
       | j                  g dddd      }|j
                  dk(  rt        j	                  d       yt        j                  d|j                  j                                 y)z=Stellt sicher, dass 'Microsoft Print to PDF' installiert ist.r   N)
powershell
-NoProfile-CommandzmGet-Printer -Name "Microsoft Print to PDF" -ErrorAction SilentlyContinue | Select-Object -ExpandProperty NameTr  capture_outputtexttimeoutzMicrosoft Print to PDFuE   'Microsoft Print to PDF' nicht gefunden – versuche Installation …)rE  rF  rG  z9Start-Service -Name Spooler -ErrorAction SilentlyContinue
   )rI  rK  )rE  rF  rG  zgAdd-Printer -Name "Microsoft Print to PDF" -DriverName "Microsoft Print To PDF" -PortName "PORTPROMPT:"r:  z%'Microsoft Print to PDF' installiert.zInstallation fehlgeschlagen: F)	
subprocessrunstdoutr   r   
returncoder   stderrr)   )rM  checkadds      r"   _ensure_ms_pdf_printerz(Abrechnungssystem._ensure_ms_pdf_printer  s     	5  dB	  
 $u||3[\J 	 	

 nnQ  dB	  
 >>QKK?@6szz7G7G7I6JKLr$   c                  t   ddl } ddl}	 | j                  g dddd      }|j                  dk(  r|j                  j                         r|j                  |j                        }t        |t              r|g}dx}}|D ]L  }|j                  dd      |j                  d	d
      xs d
} d| }t        fddD              r|}|K|}N |s|r|xs |S 	 ddl}	|	j                  |	j                  |	j                  z  dd      }
dx}}|
D ]p  }|d   |	j!                        }	 |	j#                  |d      }|	j%                  |       |j                  dd
      } d| }t        fddD              r|}|o|}r |xs |S # t        $ r Y w xY w# |	j%                  |       w xY w# t        $ r Y yw xY w)u7   Sucht einen verfügbaren Drucker für Excel-PDF-Export.r   N)rE  rF  rG  z;Get-Printer | Select-Object Name, PortName | ConvertTo-JsonTr  rH  r?  r'   PortNamezPORTPROMPT:z on c              3   B   K   | ]  }|j                         v   y wr  rk   r  kwrW  s     r"   r  z8Abrechnungssystem._find_excel_printer.<locals>.<genexpr>  s     G"2-G   )PDFXPSro  	pPortNamec              3   B   K   | ]  }|j                         v   y wr  rX  rY  s     r"   r  z8Abrechnungssystem._find_excel_printer.<locals>.<genexpr>1  s     CbrTZZ\)Cr[  )rM  r*  rN  rP  rO  r)   loadsrh   r"  r]   r  r   
win32printEnumPrintersPRINTER_ENUM_LOCALPRINTER_ENUM_CONNECTIONSOpenPrinter
GetPrinterClosePrinter)rM  _jsonresultdata	preferredfallbackpportprinter_strra  printershandler   rW  s                @r"   _find_excel_printerz%Abrechnungssystem._find_excel_printer  s    	)	^^P#$ $ F
   A%&--*=*=*?{{6==1dD) 6D'++	H /A55,D55];L}D%)F$tf"5KGGG$/	'#./ $00	!..--
0S0SSUY[\H $('I +1#//54%00;D++F3"hh{MB!%d4&1CNCC +I#*H+ ((+  		 ++F3  		sJ   B>F 
F AF+ 'F9AF+ <	F+ 	FFF((F+ +	F76F7rP  output_pdf_pathc                    ddl }ddl}dx}}	 |j                          t        j                  j                  |      st        d|       |j                  j                  d      }d|_	        d|_
        d|_        | j                         }|s | j                          | j                         }|r		 ||_        nt         j#                  d       |j$                  j'                  |      }|j)                  d|       |j+                  d       d}	 	 ||j+                  d       	 ||j-                          	 |j/                          y	# t        $ r"}t         j#                  d|        Y d}~d}~ww xY w# t        $ r Y ^w xY w# t        $ r Y Zw xY w# t        $ r Y y	w xY w# 	 ||j+                  d       n# t        $ r Y nw xY w	 ||j-                          n# t        $ r Y nw xY w	 |j/                          w # t        $ r Y w w xY wxY w)
uL   PDF-Erstellung via Excel COM (win32com). Gibt True zurück wenn erfolgreich.r   NzExcel-Datei nicht gefunden: zExcel.ApplicationFr<   z%Drucker konnte nicht gesetzt werden: u   Kein Drucker verfügbar.T)win32com.client	pythoncomCoInitializer   r   r   r   clientDispatchVisibleDisplayAlertsAutomationSecurityrr  rT  ActivePrinterr   r   r   	WorkbooksOpenExportAsFixedFormatCloseQuitCoUninitialize)	r   rP  rs  win32comrv  excelworkbookprinterpes	            r"   _create_pdf_excel_comz'Abrechnungssystem._create_pdf_excel_com:  s   )&	""$77>>*-'*Fzl(STTOO,,-@AE!EM"'E'(E$..0G++-224Q*1E' 9:++J7H((O<NN5!H'NN5)$JJL((*+ ! QNN%J2$#OPPQ  
    'NN5) $JJL ((* s   B!F" 0E 7AF" E5 #F 6F 	E2E-(F" -E22F" 5	F F	FF	FF"H$F87H8	GHGHGH	G'$H&G''H+G<;H<	HHHH
input_pathc                 6   ddl }ddl}ddl}t        j                  dk7  r$| j                  dd      } |j                  dd      }t        j                  j                  |      }t        j                  j                  dd      }t        j                  dk7  ret        j                  j                  |      sFt        j                  j                  |j                         d      }	 t        j                  |d	
       t        j                  j                         }t        j                  dk7  r||d<   |j!                  dd       d|j                  t        j"                  d      z   }|j%                  d|j                  d            xs" |j%                  d|j                  d            }	g }
|	r|
j'                  |	       |
j)                  g d       t+               }|
D cg c]  }||v r|j-                  |      r| }
}g }t.        j1                  dt3        |
       d|
        |
D ]'  }	 |j5                  |dd|z   ddd|| gd	d	d|      }|j6                  dk(  rt        j                  j                  |t        j                  j9                  t        j                  j;                  |             d   dz         }t        j                  j=                  |      r||k7  rt        j>                  ||        y	|j'                  d| d|        n?|j'                  d| d|j6                   d |j@                  jC                         dd!         * |D ]  }t.        jM                  d$|         y%# t        $ r Y w xY wc c}w # tD        |jF                  f$ r8}|j'                  d| d"tI        |      jJ                   d#|        Y d}~d}~wt        $ r8}|j'                  d| d"tI        |      jJ                   d#|        Y d}~d}~ww xY w)&z=PDF-Erstellung via LibreOffice (headless). Format-agnostisch.r   Nnt\/EEG_LO_HOMEz/var/lib/eeg-lo-profilezeeg-lo-profileTr   HOMEPATHz</usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binzfile://soffice)r   libreoffice)z/usr/bin/sofficez/usr/bin/libreofficez/usr/local/bin/sofficez/usr/local/bin/libreofficer  r  z0C:\Program Files\LibreOffice\program\soffice.exez6C:\Program Files (x86)\LibreOffice\program\soffice.exezLibreOffice-Kandidaten (z): z
--headlessz-env:UserInstallation=z--convert-topdfz--outdir   )rI  rJ  rK  env.pdf[z] rc=0 aber kein PDF in z] rc=z stderr=i,  z] r   zLibreOffice-Fehler: F)'rM  tempfileshutilr   rW  rb   r   r   environr]   isdirr   
gettempdirr   r   copyr,  r   whichr^   extendsetrS  r   r   r`   rN  rP  splitextr   r   renamerQ  r)   r   TimeoutExpiredtype__name__r   )r  rs  rM  r  r  
output_dirlo_homer  user_installresolvedlo_candidatesseencerrsr  ri  lo_pdfr   s                     r"   _create_pdf_libreofficez)Abrechnungssystem._create_pdf_libreofficef  s    	,+77d?(00s;J-55dC@OWW___5
**..0IJ77d?277==#9ggll8#6#6#8:JKGGd3 jjoo77d?!CKNN6#ab 7??2663#??LLLA I||M|H 	  * 
 	 u$1Tq!t)txxPQ{TT.s=/A.B#m_UV$ 	DGD#l-<#UZ9 $(dCS (  $$)WW\\"(()9)9*)EFqIFRF ww~~f-!_4IIfo>#KK!G9,DZL QRKKG9E&*;*;)<HV]]EXEXEZ[_\_E`Dab)	D6  	7ANN1!56	7o  , U6 &z'@'@A Day47+;+;*<BqcBCC Day47+;+;*<BqcBCCDsP   $M7 "	N,N>N1C
N=AN7	NNP!-OP -PPc                    t         j                  j                  |      }t         j                  j                  |      }t         j                  dk(  r$|j	                  dd      }|j	                  dd      }	 t
        j                  d       | j                  ||       t         j                  j                  |      rjt         j                  j                  |      rt        j                  |       t
        j                  dt         j                  j                  |              y	 	 t
        j                  d	       | j                  ||      rjt         j                  j                  |      rt        j                  |       t
        j                  d
t         j                  j                  |              yt
        j                  d       t
        j                  dt         j                  j                  |              y# t        $ r#}t
        j                  d|        Y d}~d}~ww xY w# t        $ r"}t
        j                  d|        Y d}~d}~ww xY w)uH   Erstellt PDF aus Excel. Versucht: COM → LibreOffice → Fallback XLSX.r  r  r  u    PDF-Erstellung via Excel COM …zPDF erstellt (Excel COM): TzExcel COM fehlgeschlagen: Nu"   PDF-Erstellung via LibreOffice …zPDF erstellt (LibreOffice): /LibreOffice nicht gefunden oder fehlgeschlagen.zLibreOffice fehlgeschlagen: u8   PDF-Erstellung nicht möglich – XLSX bleibt erhalten: F)r   r   abspathrW  rb   r   r   r  r   remover   r   r   r  )r   rP  rs  r   s       r"   
create_pdfzAbrechnungssystem.create_pdf  s   77??:6
77???;77d?(00d;J-55c4@O		=KK:;&&z?Cww~~o.77>>*-IIj)89I9I/9Z8[\]	 /		?KK<=++JH77>>*-IIj):277;K;KO;\:]^_NNLM 	FrwwGWGWXbGcFde	
   	=NN7s;<<	=  	?NN9!=>>	?s8   7B/H )BH4 :H4 	H1H,,H14	I=II	keep_docxc                 d   t         j                  j                  |      }t         j                  j                  |      }t         j                  dk(  r$|j	                  dd      }|j	                  dd      }	 t
        j                  d       | j                  ||      rm|s5t         j                  j                  |      r	 t        j                  |       t
        j                  dt         j                  j                  |              yt
        j                  d	       t
        j                  dt         j                  j                  |              y# t        $ r"}t
        j                  d|        Y d}~d}~ww xY w# t        $ r"}t
        j                  d
|        Y d}~d}~ww xY w)z'Wandelt DOCX via LibreOffice in PDF um.r  r  r  u1   PDF-Erstellung via LibreOffice (DOCX → PDF) …u$   DOCX konnte nicht gelöscht werden: NzPDF erstellt: Tr  z*LibreOffice-Konvertierung fehlgeschlagen: u8   PDF-Erstellung nicht möglich – DOCX bleibt erhalten: F)r   r   r  rW  rb   r   r   r  r   r  r   r   r   r   )r   r>  rs  r  r   s        r"   create_pdf_from_docxz&Abrechnungssystem.create_pdf_from_docx  sX    ''//)4	''///:77d?'//T:I-55c4@O	MKKKL++IG RWW^^I%>S		), nRWW-=-=o-N,OPQNNLM 	Fww	*+-	
  # S)MaS'QRRS
  	MNNGsKLL	MsI   7AF  E 5F F 	FE<7F <FF 	F/F**F/created_mitgliederc                    |D ]  }t         j                  j                  | j                  d|j                   d|j
                         }dD ]<  }||z   }t         j                  j                  |      s(t        j                  |       >  t         j                  j                  | j                        r>t        j                  | j                        st        j                  | j                         t         j                  j                  | j                        r>t        j                  | j                        st        j                  | j                         t        j                  d       y)uE   Löscht alle erstellten Rechnungsdateien und räumt leere Ordner auf.	Rechnung_rR  )r  z.docxz.xlsxzRollback abgeschlossen.N)r   r   r   r   r  rF  r   r  r   listdirrmdirr   r   )r   r  r  baseextr   s         r"   rollbackzAbrechnungssystem.rollback  s    * 	$H77<<&&H445Qx7M7M6NOD 2 $cz77>>$'IIdO$	$ 77>>$**+BJJt?O?O4PHHT%%&77>>$001"**TE[E[:\HHT++,01r$   c                 j   	 |j                   dk7  s|j                  dkD  s|j                  dkD  rD| xj                  dz  c_        | j                  j
                   d| j                  d|_        t        j                  j                  | j                  d|j                   d|j                   d      }| j                  ||      du}|sot        j                  d	       | j                  |      }| j!                  ||      }|s5t        j#                  d
t        j                  j%                  |              t        j                  dt'        |j(                         d|j                   d       yy# t*        $ r4}t        j-                  dt'        |j(                         d|         d}~ww xY w)uA   Rechnungsnummer vergeben, PDF erstellen (HTML → DOCX-Fallback).r   r<   r  04dr  rR  r  Nu<   WeasyPrint nicht verfügbar – Fallback: DOCX + LibreOfficeu$   PDF fehlgeschlagen – DOCX bleibt: u   Rechnung für z erstellt (Nr: z).zFehler bei r   )r  r|  r{  r   r   yearr  r   r   r   r   rF  r0  r   r   r4  r  r   r   r   r?  r   r   )r   r  pdf_basepdf_okr>  r   s         r"   process_mitgliedz"Abrechnungssystem.process_mitglied  s   	!#x':':Q'>(BVBVYZBZ$$)$**//0$2F2Fs1KL ( 77<<** 8 898;Q;Q:RRVW 55hIQUUKK ^_ $ 8 8 BI $ 9 9)X NF!B277CSCST]C^B_` $%6x}}%E$FoV^VnVnUooqr1 C[6  	LL;'8'G&H1#NO	s   E1E5 5	F2>/F--F2c                     | j                   j                  d| j                   j                  dd            j                         j                         dk(  S )z.True wenn Abbuchungsmodus = abrechnungsverein.r  r,   r-   r  )r   r]   r)   rj   r   s    r"   _is_av_modezAbrechnungssystem._is_av_mode"  sA    {{t{{/@.Q

%'%%'01 	1r$   c                     | j                         rt        d   t        d   t        d   fS | j                  j                  dd      | j                  j                  dd      | j                  j                  dd      fS )uG   Gibt (IBAN, BIC, Creditor_ID) zurück – AV-Modus: aus _AV_KONSTANTEN.r   rt   r   r  r'   r  r  )r  r   r   r]   r   s    r"   	_sepa_idszAbrechnungssystem._sepa_ids(  ss    v&u%}-  KKOOK,KKOOJ+KKOO.3
 	
r$   c                      ddl m}  ||        y)u@   Prüft SEPA-Konfigurationswerte. Delegiert an core.sepa_handler.r   )_validate_sepa_configN)core.sepa_handlerr  )r   r  s     r"   r  z'Abrechnungssystem._validate_sepa_config6  s    ;d#r$   c                 :   |j                   r|j                  s"t        dt        |j                         d      d| j
                   t        |j                        t        |j                         t        t        t        |j                        dz              |j                  |j                  t        j                         | j                  j                         | j                  d    d| j
                   d|j                    d| j#                         d   dd	S )
u1   Erstellt ein SEPA-Payment-Dict für ein Mitglied.z	Mitglied u    hat keine gültige IBAN/BICzLastschrift-r  r.   r  OOFFro  )PmtInfIdrW  r7   amountr9   
mandate_idmandate_datecollection_dater  sequencer   r  )r7   r9   rf   r   r?  r   r(   rg   r  re   r  r>  r   todayr   r   r  r  )r   r  s     r"   _create_sepa_paymentz&Abrechnungssystem._create_sepa_payment;  s    }}HLLy):8==)I(JJfghh ,T\\N;!(--0!(--0!%hoo(>(D"EF&ll&kk"jjl#3388:!%]!; <Adll^1XMeMeLfg$"nn.q1$
 	
r$   xml_contentc                     	 t        |d      5 }|j                  |       ddd       y# 1 sw Y   yxY w# t        $ r}t        d| d|       d}~ww xY w)z"Schreibt XML-Inhalt in eine Datei.wbNz$Fehler beim Schreiben der XML-Datei r   )r)  writeIOError)r   r.  r  fr   s        r"   _write_xml_filez!Abrechnungssystem._write_xml_fileN  s`    	Uk4( %A$% % % 	U@RPQsSTT	Us(   5 )5 25 5 	AAAc                      ddl m}  ||        y)z>Erstellt SEPA-Lastschrift-XML. Delegiert an core.sepa_handler.r   )create_sepa_xml_lastschriftN)r  r  )r   r  s     r"   create_sepa_xml_Lastschriftz-Abrechnungssystem.create_sepa_xml_LastschriftV  s    A#D)r$   c                      ddl m}  ||        y)z=Erstellt SEPA-Gutschrift-XML. Delegiert an core.sepa_handler.r   )create_sepa_xml_gutschriftN)r  r  )r   r  s     r"   create_sepa_xml_Gutschriftz,Abrechnungssystem.create_sepa_xml_Gutschrift[  s    @"4(r$   c                     ddl m}  ||       S )Delegiert an core.sepa_handler.r   )_create_sepa_ct_object)r  r  )r   r  s     r"   r  z(Abrechnungssystem._create_sepa_ct_object`  s    <%d++r$   gutschrift_mitgliederc                 $    ddl m}  ||||        y)r  r   )_add_gutschrift_transactionsN)r  r  )r   sepa_ctr  r  s       r"   r  z.Abrechnungssystem._add_gutschrift_transactionse  s    B$W.CTJr$   c                 $    ddl m}  ||||        y)r  r   )_export_sepa_ctN)r  r  )r   r  r.  r  s       r"   r  z!Abrechnungssystem._export_sepa_ctj  s    5d3r$   sepa_folderc                      ddl m}  ||       y)r  r   )_validate_sepa_folderN)r  r  )r   r  r  s      r"   r  z'Abrechnungssystem._validate_sepa_foldero  s    ;k*r$   r/   domainc                     t        | |      S )zDelegiert an core.utils.)r   )r/   r  s     r"   _vereinsname_to_from_emailz,Abrechnungssystem._vereinsname_to_from_emailv  s     )f==r$   
test_emailc                 $    ddl m}  || ||       y)zCVersendet die Rechnung per E-Mail. Delegiert an core.email_handler.r   )
send_emailN)core.email_handlerr  )r   r  r  r  s       r"   r  zAbrechnungssystem.send_email|  s    14:.r$   to_addrr   c                 $    ddl m}  || ||       y)z=Sendet SEPA-XMLs per E-Mail. Delegiert an core.email_handler.r   )send_sepa_emailN)r  r  )r   r  r   r  s       r"   r  z!Abrechnungssystem.send_sepa_email  s    6gw/r$   rows2fnamec                 (  >?@ABCDE ddl m}  || |       d}d}d}d}d}d}	t        j                  d	|        t	        |      |	k  rt        j                  d
       y||   }
||   }||   }||   }||   }| j                  j                  dd      }| j                  j                  dd      }g }t        dt	        |
            D ]Z  B|
B   }|B   }|B   }|B   }|s|dvs|||fv s&|s)t        |t        t        f      s@|j                  B|||||B   d       \ |st        j                  d       yt	        |      |	z
  }d }g }|d   d   }|r||k7  r|j                  d| d|        t        |	t	        |            D cg c]  } |||   d          }}|D cg c]  }||	 c}Et        d      Ct        CEfdt        dt	        E            D              }|r|j                  | d       g }|D ]S  }|d   dk(  r|d   Bt        Bfd||	d D              } | s+|j                  |d    d|d    d|d    dd!  d"|  d#       U ||z   D ]  }!t        j                  d$|!         |s'|s%t        j                  d%| d&t	        |       d'       d(}"g }#|D ]j  }|d   Bt        Bfd)||	d D              }$t        |$|d   z
        }%|%|"kD  s6|#j                  |d    d|d    d|d    dd!  d*|d   d+d,|$d+d-|%d+d.       l |#D ]  }!t        j                  d/|!         |#s"t        j                  d0t	        |       d1       d2}&t        d3 | j                   D              }'t        d4 | j                   D              }(t        |'|(z
        })|)|&k\  r#t        j                  d5|'d+d6|(d+d7|)d+d8       nt        j                  d9|)d:d;       | j                  j                  d<d=      }*|D +cg c]  }+|+d    |*k(  r|+d   |k(  r|+d    },}+	 dd>lm}- dd?lm> i d@dAdBdAdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdTdVdTdWdXdYdZd[d\d]d^i d_d`dadbdcdddedfdgdfdhdidjdkdldkdmdkdndodpdqdrdsdtdudvdwdxdydzd{d|d}d~ddddddddd	}.dA}/t+        | j                  j                  dd            j-                         }0|0j/                         j-                         }1|.j                  |1      }2|2$|.j1                         D ]  \  }3}4|3|1v s|1|3v s|4}2 n |2|/}2t        |/|2z
  dz        @ |-dddd|/      ?i A>?@Afd}5g }6||	d D ]f  D |Dd         }7|7 |5|7j3                               \  }8}9|7|8k  s|7|9k\  s5t        Dfd|,D              }:|6j                  t5        |:dz  d             h |6j7                  d       t	        |6      };|;dkD  r,|;dz  }<t        d      D cg c]  }|6t        ||<z            }6}|6| _        t        j                  d|; d|6r
d|6d   ddnd=z          yc c}w c c}w c c}+w c c}w # t:        $ r)}=t        j                  d|=        g | _        Y d}=~=yd}=~=ww xY w)u   Prüft Spaltensummen, Zeitreihen-Vollständigkeit und Energiebilanz.
        Berechnet auch stündliche KPI-Kurven und die Nacht-Jahresdauerlinie.r   )compute_hourly_kpisr<   r\   r9     r     u(   Starte Integritätsprüfung EDA-Report: u9   Integritätsprüfung: Blatt 2 enthält keine Datenzeilen.Nr   
GENERATIONr   CONSUMPTION)MMTOTAL)rq  r  dircodepre_sum
n_expectedu2   Integritätsprüfung: Keine Datenspalten gefunden.c                     | y t        |       j                         }dD ]  }	 t        j                  ||      c S  y # t        $ r Y )w xY w)N)z%d.%m.%Y %H:%Mz%d.%m.%Y %H:%M:%Sz%Y-%m-%d %H:%M:%S)r(   r)   r   rO  rf   )r*   sfmts      r"   	_parse_tszDAbrechnungssystem._validate_eda_sheet_consistency.<locals>._parse_ts  sY    yAAS #,,Q44
  " s   =	A	A	r  zAnzahl Datenzeilen u    ≠ Z13-Angabe )minutesc              3   D   K   | ]  }|   |d z
     z
  k7  rd   yw)r<   N )r  iintervalvalid_tss     r"   r  zDAbrechnungssystem._validate_eda_sheet_consistency.<locals>.<genexpr>  s2      
{Xa!e_,8 
s    u0    Zeitstempel-Lücke(n)/Sprünge im 15-Min-Rasterr  rq  c              3   .   K   | ]  }|   	d  y w)Nr<   r  r  rcis     r"   r  zDAbrechnungssystem._validate_eda_sheet_consistency.<locals>.<genexpr>  s     Mqu}!Ms   
r  r  r  r  2   r   z Werte fehlenu   Vollständigkeitsprüfung: u!   Vollständigkeitsprüfung OK – z Zeitintervalle, u    Spalten vollständig.gMbP?c              3   Z   K   | ]"  }t        |   t        t        f      r|    $ y wr  rh   rg   re   r  s     r"   r  zDAbrechnungssystem._validate_eda_sheet_consistency.<locals>.<genexpr>  s/      aec5\2 "   (+z: Z16=r  u    ≠ Σ=u    (Δ=z kWh)zSpaltensummen-Abweichung: u&   Spaltensummen-Integrität OK – alle z Spalten korrekt.r  c              3   4   K   | ]  }|j                     y wr  r  r  s     r"   r  zDAbrechnungssystem._validate_eda_sheet_consistency.<locals>.<genexpr>  s     BQ1==Br  c              3   4   K   | ]  }|j                     y wr  r  r  s     r"   r  zDAbrechnungssystem._validate_eda_sheet_consistency.<locals>.<genexpr>   s     BQ1<<Br  u   Energiebilanz-Abweichung: Σ C=u    kWh, Σ G=u	    kWh, Δ=z kWhu   Energiebilanz OK – Δ=z.6fz kWh.r   r'   )LocationInfo)sunwiengQ^0@viennagrazgzG.@linzgGz,@salzburggGz*@	innsbruckgHz&@
klagenfurtgQ,@villachg33333+@welsg
ףp=
,@steyrgףp=
,@u   st. pölteng=
ףp=/@u
   st pöltenu   sankt pöltendornbirng{Gz#@bregenzg     #@	feldkirchg333333#@leondingg     ,@traung{Gz,@klosterneuburggRQ0@u   mödlingg
ףp=J0@zkrems an der donaugQ8/@krems	amstetteng=
ףp-@zwaidhofen an der ybbsg
ףp=-@zwaidhofen/ybbs	waidhofenleobengGz..@
kapfenberggGz.@zbruck an der murg(\.@	wolfsberggGz-@kufsteingףp=
W(@imstg{Gz%@lienzg
ףp=)@zzell am seeg)@g=
ףp=+@g+@gRQ+@g{G*@g=
ףp=0@gQ0@gRQ/@gףp=
W.@g)\.@)	z	bad ischlgmundenu   vöcklabruckzried im innkreiszwiener neustadt
eisenstadthornzwettlmelkSuncityViennag      @AustriazEurope/ViennagH@c                     | vrV j                   | j                        }|d   j                  d       z   }|d   j                  d       z   }||f| <   |    S )N)r   r<  sunriser;  sunset)observertimezonerb   )dr
  srss_astral_sun	_location_lon_offset
_sun_caches       r"   _get_sunrise_sunsetzNAbrechnungssystem._validate_eda_sheet_consistency.<locals>._get_sunrise_sunset8  st    J&$Y%7%7a	HZHZ[A9--T-:[HB8,,D,9[HB%'HJqM!!}$r$   c              3   Z   K   | ]"  }t        |   t        t        f      r|    $ y wr  r  )r  r  rS  s     r"   r  zDAbrechnungssystem._validate_eda_sheet_consistency.<locals>.<genexpr>G  s/      )$&%c"gU|< B)r  r=   T)reversei  zNacht-Jahresdauerlinie: z Nachtstunden-Intervallez, Peak r  z kW)r  r  r   r   r`   r   r   r]   rangerh   rg   re   r^   r   r  r  r   astralr  
astral.sunr  r(   r)   rj   r   r   r  sortr   r   )Fr   r  r  r  IDX_ZPIDX_DIRIDX_CODE
IDX_N_INTVIDX_SUM_PREIDX_DATA_STARTrow_zprow_dirrow_code
row_n_intvrow_sum_pre	dir_g_val	dir_c_val	data_colsr  dirnr  pren_data_rowsr  errors_completenessn_expected_refr  
timestampst	gap_countmissing_colscolmissingmsgTOLERANCE_COL
sum_errorscomputeddiffTOLERANCE_BALANCEsum_csum_gbalance_diffcode_ges_verbr  ges_verb_colsr  _AT_LON_VIENNA_LON	city_namecity_keycity_lonk_citylonrL  nighttime_kwtsrF  rG  total_verb_kwhn_fullstep_e_nightrH  rI  rJ  rK  r  r  rS  r  sF                                                                 @@@@@@@@r"   _validate_eda_sheet_consistencyz1Abrechnungssystem._validate_eda_sheet_consistency  s    	8D%(
>ugFGu:'NNVWFmGnHoJ'
K(KKOO$5|D	KKOO$5}E		3v;' 	B":B2;DB<Dr?Cr0I 66C#u!>  Rd"*R." 	 NNOP%j>1		 %'"1l3k^;&&%k]2B>BRS 7<NCPUJ6WXia,X
X!+=Aq}a=r* 
QH.
 
	 &&+MN   	C9~"%jBMU>?%;MMG##4ykSZLCK4D3ERyP]^	 '5 	@CNN8>?	@"<KK3K=@Qy>""8: 
 	C5zB $^_5 H x#i.01Dm#!!4ykSZLCK4D3E Fy>#.hxnE$sSXZ	  	?CNN7u=>	?KK8Y8HHYZ
  B$//BBB$//BB55=),,NN1% =c{)L+=TC
 KK2<2DEJK (=rB'
yM)ah).C eH
 
J	1+5'%u.8% U %1% :CE 	  '	
 u
 '3E
 <KE D #,T 4? E $+E !% *4U %e .5e U %<U !% *5e % ".u #E ,7 E $*5 3:5 u 49U %5#(%G(  KdkkooiBCIIKI#//+113H!++h/H#*==? KFC)X-?#& &#kH.D-KMK&xOTS^_I!J% "$L^_- 
Hs1v&:,RWWY7B7bBh%( )*7) &N !''ns.BA(FG
H d+&F}%}EJ4[QST] ;QQ.:D+KK*6(2JK9EW\!_S152OU Y=B
J  R  	1NN5hZ@A.0D++	1sQ   Y(Y0YY%DY ,A,Y A(Y Y1Y Y 	Z(ZZreport_pathsc                    	 || _         | j                          | j                          |D ]  }| j                  |        | j	                  | j
                        s t        j                  d       t        d       | j                          | j
                  j                  d        t        j                  j                  | j                  d| j                  d         }| j!                  |      | _        g }	 | j
                  D ]$  }|j%                  |       | j'                  |       & 	 | j-                          | j/                          | j
                  D ]q  }|j0                  d
k7  s|j2                  d
kD  s|j4                  d
kD  s1| j                  j7                  dd      dk(  r| j9                  |       | j;                  |       s t        j=                  d       y	# t(        $ r0}t        j                  d| d       | j+                  |        d	}~ww xY w# t(        $ r }t        j                  d| d        d	}~ww xY w)z/Hauptablauf (Legacy): Alles in einem Durchgang.z8Abbruch: Consumption und Generation weichen zu stark ab!r<   c                     | j                   dkD  rd| j                  fS | j                   dk  rd| j                  fS d| j                  fS Nr   r<   ro  r  r>  r  s    r"   r  z'Abrechnungssystem.run.<locals>.<lambda>m  sF    XX\1440 -.XX\1440 ?@1440 r$   rv   r   r!  zFehler: u#   . Setze alle Änderungen zurück...Nr   	Send_MailFalseTruezFertig! Rechnungen erstellt.T)exc_info)r   r   rc  r  r  r   r   r   r   r  rR  r   r   r   r   r   r  r   r^   r  r   r  r  r  r  r|  r{  r]   r  r  r   )r   r  r   r_pr  created_rechnungenr  r   s           r"   rN  zAbrechnungssystem.run^  s   ,	"DLOO  "# *$$S)*44T__EWXQ!!#OO   &   $&77<<dkk:P.Q$  $(#A#ABV#WD !# $ 4H&--h7))(34 ,,.++- OO :??a'8+>+>+BhFZFZ]^F^{{{G<F1//9	:
 KK67  xs*MNO01  	LL8A3$L7	sD   C7H  :3G$ -AH  AH  $	H-+HHH   	I	)II	c                    || _         | j                          | j                          |D ]  }| j                  |        	 | j	                  | j
                        }|st        j                  d       | j                          g }| j
                  D ]	  }	 t        t        |dd      xs d      }	 t        t        |dd      xs d      }		 t        t        |dd      xs d      }
|j                  t        |d	d
      t        |dd
      xs d
t        |dd
      xs d
t        |dd
      xs d
t        |dd
      xs d
t        |dd
      xs d
t        |d      t        |	d      t        |
d      t        t        |dd      xs d      t        |
      dkD  d        d| _        |S # t        $ r#}t        j                  d|        Y d}~[d}~ww xY w# t        $ r d}Y 4w xY w# t        $ r d}	Y +w xY w# t        $ r d}
Y "w xY w)zWPhase 1: Mitglieder + EDA einlesen, Kosten berechnen. Keine Dateien werden geschrieben.z,Consumption und Generation weichen stark ab.zBilanz-Check fehlgeschlagen: Nr{  r   r   r|  r  r>  r'   r?  rA  r7   rD  rE  r\   ro  r  g{Gzt?)rn  rW  rf  r   r*  r+  r  r  kostenri  has_invoiceT)r   r   rc  r  r  r   r   r   r   r  re   r~  r^   r  rg   r  	_prepared)r   r  r   r  oke_balri  r  r  r  r  s              r"   preparezAbrechnungssystem.prepare  s    	&C  %	&	D224??CBMN 	 	A"#GA}a$@$EAF!"71lA#>#C!D
wq(A6;!< MM&q$3&q&"5;&q&"5;&q&"5;&q*:B?E2&q/2>D"$[!4$Z3$VQ/"71lA#>#C!D"6{U2 	6 E  	DNN:5'BCC	D  "!"  ! 
!  sN   2F' G1G(G:'	G0GGG%$G%(G76G7:H	H	start_rechnungsnummerc           	         t        | dd      st        d      |dkD  r?|| _        t        j	                  d| d| j
                  j                   d|dz   d	d
       nNt        j                  j                  | j                  d| j                  d         }| j                  |      | _        | j                  j                  d        g }	 | j                  D ]$  }|j                  |       | j!                  |       & y# t"        $ rW t        j%                  d       	 | j'                  |        # t"        $ r"}t        j%                  d|        Y d}~ d}~ww xY ww xY w)z6Phase 2: Rechnungsnummern vergeben + PDF pro Mitglied.r  Fz5generate_pdfs() ohne vorheriges prepare() aufgerufen.r   zRechnungsnummern-Start: u    (nächste: r  r<   r  r   r   r!  c                     | j                   dkD  rd| j                  fS | j                   dk  rd| j                  fS d| j                  fS r  r  r  s    r"   r  z1Abrechnungssystem.generate_pdfs.<locals>.<lambda>  sF    AAqtt,
 )*AAqtt,
 ;<qtt,
 r$   r  u%   Fehler in generate_pdfs – rollback.zRollback fehlgeschlagen: N)r~  RuntimeErrorr   r   r   r   r  r   r   r   r   r   r  r   rR  r^   r  r   r   r  )r   r  r  createdr  e_rbs         r"   generate_pdfszAbrechnungssystem.generate_pdfs  sd   t[%0VWW 1$#8D KK*+@*A B"11667q9Nq9PQT8UUVX
 gglldkk:P.QG $(#A#A'#JD  "
 	 
	__ )q!%%a()  	LL@AAg&   A8?@@A		s6   3C? ?ED0/E0	E9EEEEc                 t    t        | dd      st        d      | j                          | j                          y)z9Phase 3: SEPA-Lastschrift- und -Gutschrift-XML schreiben.r  Fz6build_sepa_xml() ohne vorheriges prepare() aufgerufen.N)r~  r  r  r  r   s    r"   build_sepa_xmlz Abrechnungssystem.build_sepa_xml  s2    t[%0WXX((*'')r$   c           
         t        | dd      st        d      dD ]  }t        | |      rt        | |d        dD ]  }t        | |      rt        | |d        g g }}| j                  D ]I  }	 |j
                  dk(  r| j                  |      }|(|j
                  dkD  r|n|j                  |       K | j                  dkD  s| j                  dkD  r	 | j                  ||       y	t        j                  d       y	# t        $ r0}t        j                  d
t        |dd       d|        Y d	}~d	}~ww xY w# t        $ r"}t        j                  d|        Y d	}~y	d	}~ww xY w)u6   Phase 4: Kassabuch-Einträge + Sammelzeilen schreiben.r  Fz7write_kassabuch() ohne vorheriges prepare() aufgerufen.)r   r   r'   )r   r   r   r   Nu   Kassabuch-Zeile für r?  ?z fehlgeschlagen: z9Kassabuch-Sammelzeilen konnten nicht geschrieben werden: uA   Kassabuch: SEPA nicht mitgelaufen – Sammelzeilen übersprungen.)r~  r  hasattrr  r   r  r  r^   r   r   r   r   r   r  r   r   )r   attrr  r  r  row_nre_hre_bss           r"   write_kassabuchz!Abrechnungssystem.write_kassabuch  sw   t[%0XYY. 	(D4&dB'	( 3 	)D4&dC(	) r 	A
88q=44Q7>HHqLg==fE	 a4#3#3a#7c33GWE KK[\  +GAvs,C+DDUVZU[\   c!Z[_Z`abbcs<   /C??C?"C?D; ?	D8&D33D8;	E&E!!E&)r   Nr  )NN)F)zenergie-durchdacht.at)r'   )r   )Gr  
__module____qualname____doc__r(   r   r   r   r   r   r   rc  r#  SeriesrK  listru  r  r  ri   r  r   r  r  r  rg   r  r  r  r  r  r"  r-  r0  r4  r7  r9  r<  staticmethodrA  rC  rT  rr  r  r  r  r  r  r  r  r   r  r  r  bytesr  r  r  r  r  r  r  r  r  r  r  rN  r  r  r  r  r  r$   r"   r   r      s   # >-     .vT#s(^ vtNC`G		 G4S> G:0d 0d3)n23 2
$ "8 "")) "+/S>">B".=BII =tCH~ =0>84c 4c 4
ax aL a2( s 
3 
( 
58
AD
IL

d 
T 
d 
"H
H H
 H
V 48D D-0D<HD 26/3OH O+.O),O8;O-h -3 -
I( It I,
 2s 2s 2t 2 2
     D  : 0 0d* *c *d *X DC D# D$ D DLS 3 4 B 16c C )-:>:24 2D 2&! !d !J1T 1
5 
$

X 
$ 
&U3 UU Ut U*
)
,
K4 KTX K
4C 4D 4
+ + + 2I> >,/>NQ> >
/8 / /
0s 0S 0R1T R1# R1$ R1l. .c .`/D /3 /4 /b 3  t  D* ]r$   r   )4r  r*  loggingmathr   randomcollectionsr   r   r   r   typingr   r   pandasr#  openpyxlr	   r
   openpyxl.stylesr   r   r   tkintertkr   ImportErrorcore.modelsr   r   r   r   r   r   r   r   
core.utilsr   r   r   r   r   basicConfigINFO	getLoggerr  r   r(   ri   r#   r}   r   r  r$   r"   <module>r     s       	  # . .   , 8 8"  
 r q   ',,/Z [			8	$c d 
rr\] \]g  	BJs   
B8 8	CC