Compare commits
3 Commits
1ca6c76b97
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65e6763395 | ||
|
|
3e36a1513e | ||
|
|
936a00c81f |
31
main.py
31
main.py
@@ -34,12 +34,15 @@ ox_quota_sus = 5120 # oxUserQuota LuL
|
|||||||
#######################
|
#######################
|
||||||
# MAIN FUNCTION START #
|
# MAIN FUNCTION START #
|
||||||
|
|
||||||
|
# .venv\Scripts\activate
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
school_folder = "7114SadW"
|
||||||
|
|
||||||
# Erstellt oder löscht Inhalte vorhandener Logdatei und loggt Konsolenausgaben
|
# Erstellt oder löscht Inhalte vorhandener Logdatei und loggt Konsolenausgaben
|
||||||
log_file_path = 'output/log.txt'
|
log_file_path = f'./Data/{school_folder}/gen_log.txt'
|
||||||
import_command_path = 'output/import_command.txt'
|
import_command_path = f'./Data/{school_folder}/gen_importCommand.txt'
|
||||||
if os.path.exists(log_file_path):
|
if os.path.exists(log_file_path):
|
||||||
open(log_file_path, 'w').close()
|
open(log_file_path, 'w').close()
|
||||||
sys.stdout = Logger.Logger(log_file_path)
|
sys.stdout = Logger.Logger(log_file_path)
|
||||||
@@ -52,14 +55,14 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
# ToDo Daten mit UI einlesen
|
# ToDo Daten mit UI einlesen
|
||||||
# lehrer_liste_neu = "./Data/SaM/export_lehrer_SaM.csv"
|
# lehrer_liste_neu = "./Data/SaM/export_lehrer_SaM.csv"
|
||||||
school_folder = "HMS"
|
|
||||||
lehrer_liste_neu = f"./Data/{school_folder}/export_lul.csv"
|
lehrer_liste_neu = f"./Data/{school_folder}/export_lul.csv"
|
||||||
lehrer_liste_system = f"./Data//{school_folder}/sys_lul.csv"
|
lehrer_liste_system = f"./Data/{school_folder}/sys_lul.csv"
|
||||||
lul_out_path = 'output/outputLehrer.csv'
|
lul_out_path = f'./Data/{school_folder}/gen_Lehrer.csv'
|
||||||
|
|
||||||
schueler_liste_neu = f"./Data/{school_folder}/export_sus.csv"
|
schueler_liste_neu = f"./Data/{school_folder}/export_sus.csv"
|
||||||
schueler_liste_system = f"./Data/{school_folder}/sys_sus.csv"
|
schueler_liste_system = f"./Data/{school_folder}/sys_sus.csv"
|
||||||
sus_out_path = 'output/outputSchueler.csv'
|
sus_out_path = f'./Data/{school_folder}/gen_Schueler.csv'
|
||||||
|
|
||||||
# Variablen füllen:
|
# Variablen füllen:
|
||||||
if not dev:
|
if not dev:
|
||||||
@@ -75,9 +78,11 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
lul_new = step1.check_export_file(lehrer_liste_neu)
|
lul_new = step1.check_export_file(lehrer_liste_neu)
|
||||||
lul_sys = step1.create_dataframe_system(lehrer_liste_system)
|
lul_sys = step1.create_dataframe_system(lehrer_liste_system)
|
||||||
|
step1.check_quotas(lul_sys, mail_quota_lul, ox_quota_lul)
|
||||||
|
|
||||||
sus_new = step1.check_export_file(schueler_liste_neu)
|
sus_new = step1.check_export_file(schueler_liste_neu)
|
||||||
sus_sys = step1.create_dataframe_system(schueler_liste_system)
|
sus_sys = step1.create_dataframe_system(schueler_liste_system)
|
||||||
|
step1.check_quotas(sus_sys, mail_quota_sus, ox_quota_lul)
|
||||||
|
|
||||||
# Test- und Funktionsuser auslagern
|
# Test- und Funktionsuser auslagern
|
||||||
keywords = ['Test', 'test', 'Raum', 'raum', 'User', 'user', 'Tafel', 'tafel', 'Admin', 'admin']
|
keywords = ['Test', 'test', 'Raum', 'raum', 'User', 'user', 'Tafel', 'tafel', 'Admin', 'admin']
|
||||||
@@ -89,17 +94,21 @@ if __name__ == "__main__":
|
|||||||
# ---------------------------------------------------- #
|
# ---------------------------------------------------- #
|
||||||
# Step 2 - auf name, vorname reduzieren und abgleichen #
|
# Step 2 - auf name, vorname reduzieren und abgleichen #
|
||||||
|
|
||||||
|
# Klassen Übersicht leeren
|
||||||
|
with open(f'./Data/{school_folder}/gen_klassen.txt', 'w') as file:
|
||||||
|
file.write('')
|
||||||
|
|
||||||
|
lul_exel_path = f'./Data/{school_folder}/gen_stats_lul.xlsx'
|
||||||
|
sus_exel_path = f'./Data/{school_folder}/gen_stats_sus.xlsx'
|
||||||
|
|
||||||
print("\n Lehrer:innen:")
|
print("\n Lehrer:innen:")
|
||||||
lul_matched, new_lul = step2.compare_data(lul_new, lul_sys, len(lul_testuser_df))
|
lul_matched, new_lul = step2.compare_data(lul_new, lul_sys, len(lul_testuser_df), lul_exel_path, school_folder)
|
||||||
print("\n Schüler:innen:")
|
print("\n Schüler:innen:")
|
||||||
sus_matched, new_sus = step2.compare_data(sus_new, sus_sys, len(sus_testuser_df))
|
sus_matched, new_sus = step2.compare_data(sus_new, sus_sys, len(sus_testuser_df), sus_exel_path, school_folder)
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------------------#
|
# ----------------------------------------------------------------------------------------#
|
||||||
# Step 3 - Import Data generieren - klasse, uuids, weiteres in einer Liste zusammenführen #
|
# Step 3 - Import Data generieren - klasse, uuids, weiteres in einer Liste zusammenführen #
|
||||||
|
|
||||||
# ToDo verfügbare Klassen listen und abgleichen
|
|
||||||
# ToDo Quota Abweichungen ermitteln und übernehmen
|
|
||||||
|
|
||||||
# Lul: Namen + UUIDs + Testuser
|
# Lul: Namen + UUIDs + Testuser
|
||||||
step3.create_output_list('LuL', new_lul, lul_matched, dev, school_id, ox_context,
|
step3.create_output_list('LuL', new_lul, lul_matched, dev, school_id, ox_context,
|
||||||
mail_quota_lul, ox_quota_lul, lul_testuser_df, lul_out_path)
|
mail_quota_lul, ox_quota_lul, lul_testuser_df, lul_out_path)
|
||||||
|
|||||||
@@ -1,40 +1,37 @@
|
|||||||
Schul-IT UCS-Import Tool:
|
Schul-IT UCS-Import Tool:
|
||||||
|
|
||||||
Eingabefelder:
|
|
||||||
Schul-ID eingeben HL070:OX-Context der Schule eingeben:Klassen mit f<>hrenden Nullen? (y/n)
|
|
||||||
Schul ID: HL0707103
|
|
||||||
OX-Context: 15
|
|
||||||
Nullen: True
|
|
||||||
|
|
||||||
Anzahl Test- / Systemuser LuL: 0
|
Schul ID: HL
|
||||||
Anzahl Test- / Systemuser SuS: 0
|
OX-Context: 0
|
||||||
|
Nullen: False
|
||||||
|
|
||||||
|
Anzahl Test- / Systemuser LuL: 2
|
||||||
|
Anzahl Test- / Systemuser SuS: 1
|
||||||
|
|
||||||
Lehrer:innen:
|
Lehrer:innen:
|
||||||
|
|
||||||
Eintr<EFBFBD>ge in System Liste: 60
|
Eintr<EFBFBD>ge in System Liste: 101
|
||||||
Eintr<EFBFBD>ge in Import Liste: 52
|
Eintr<EFBFBD>ge in Import Liste: 89
|
||||||
|
|
||||||
Anzahl neuer Nutzer: 20
|
Anzahl neuer Nutzer: 4
|
||||||
Anzahl <20>bereinstimmungen: 32
|
Anzahl <20>bereinstimmungen: 87
|
||||||
Anzahl veralteter Nutzer: 28
|
Anzahl veralteter Nutzer: 14
|
||||||
M<EFBFBD>gliche Tippfehler: keine Fehler gefunden!
|
M<EFBFBD>gliche Tippfehler: 1
|
||||||
|
Import System
|
||||||
|
0 [Martin, Herrmann] [Martin, Hermann]
|
||||||
|
|
||||||
Sch<63>ler:innen:
|
Sch<63>ler:innen:
|
||||||
|
|
||||||
Eintr<EFBFBD>ge in System Liste: 296
|
Eintr<EFBFBD>ge in System Liste: 973
|
||||||
Eintr<EFBFBD>ge in Import Liste: 491
|
Eintr<EFBFBD>ge in Import Liste: 1011
|
||||||
|
|
||||||
Anzahl neuer Nutzer: 426
|
Anzahl neuer Nutzer: 168
|
||||||
Anzahl <20>bereinstimmungen: 65
|
Anzahl <20>bereinstimmungen: 844
|
||||||
Anzahl veralteter Nutzer: 231
|
Anzahl veralteter Nutzer: 129
|
||||||
M<EFBFBD>gliche Tippfehler: 3
|
M<EFBFBD>gliche Tippfehler: keine Fehler gefunden!
|
||||||
Import System
|
|
||||||
0 [Bilal, Ismail] [Dilan, Ismail]
|
|
||||||
1 [Iyed, Khalil] [Ines, Khalil]
|
|
||||||
2 [Nicklas, Linke] [Niklas, Janke]
|
|
||||||
|
|
||||||
0 Testuser angef<65>gt - 52 Eintr<74>ge in LuL Liste
|
2 Testuser angef<65>gt - 91 Eintr<74>ge in LuL Liste
|
||||||
LuL Import CSV unter output/outputLehrer.csv erfolgreich erstellt!
|
LuL Import CSV unter output/outputLehrer.csv erfolgreich erstellt!
|
||||||
|
|
||||||
0 Testuser angef<65>gt - 491 Eintr<74>ge in SuS Liste
|
1 Testuser angef<65>gt - 1012 Eintr<74>ge in SuS Liste
|
||||||
SuS Import CSV unter output/outputSchueler.csv erfolgreich erstellt!
|
SuS Import CSV unter output/outputSchueler.csv erfolgreich erstellt!
|
||||||
|
|||||||
@@ -10,3 +10,5 @@ def generate_commands(path, sid, context, short):
|
|||||||
|
|
||||||
file.write('# Ohne Dry Run ausführen')
|
file.write('# Ohne Dry Run ausführen')
|
||||||
file.write('# Summary kopieren (sudo cp <summary path> .)')
|
file.write('# Summary kopieren (sudo cp <summary path> .)')
|
||||||
|
file.write('# Neue Listen in ucs-export generieren')
|
||||||
|
file.write()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
# Laden Sie die Excel-Datei mit mehreren Seiten
|
# Laden Sie die Excel-Datei mit mehreren Seiten
|
||||||
excel_file = pd.ExcelFile('C:/Users/Patrick vom Hagen/Documents/Import/Falkenfled/Schüler und Schülerinnen gesamt.xls')
|
excel_file = pd.ExcelFile('C:/Users/Patrick vom Hagen/PycharmProjects/UCS_Import_Python/Data/5104OzD/OzD_Abendgymnasium.xlsx')
|
||||||
|
|
||||||
dfs = []
|
dfs = []
|
||||||
for sheet_name in excel_file.sheet_names:
|
for sheet_name in excel_file.sheet_names:
|
||||||
|
|||||||
44
src/step1.py
44
src/step1.py
@@ -12,7 +12,9 @@ def check_export_file(path):
|
|||||||
|
|
||||||
# Try: Datei in pandas einlesen
|
# Try: Datei in pandas einlesen
|
||||||
try:
|
try:
|
||||||
return pd.read_csv(path, encoding=detected_encoding, sep=';')
|
df = pd.read_csv(path, encoding=detected_encoding, sep=';')
|
||||||
|
df = check_columns(df)
|
||||||
|
return df
|
||||||
# Catch: zusätzliche Kommas entfernen
|
# Catch: zusätzliche Kommas entfernen
|
||||||
except pd.errors.ParserError as e:
|
except pd.errors.ParserError as e:
|
||||||
# Wenn ein Parserfehler auftritt, gibt eine Fehlermeldung aus
|
# Wenn ein Parserfehler auftritt, gibt eine Fehlermeldung aus
|
||||||
@@ -26,18 +28,45 @@ def check_export_file(path):
|
|||||||
print(f"Alle Kommas entfernt, einlesen wir erneut versucht ...")
|
print(f"Alle Kommas entfernt, einlesen wir erneut versucht ...")
|
||||||
# Nach Komma Ersetzung erneut versuchen
|
# Nach Komma Ersetzung erneut versuchen
|
||||||
try:
|
try:
|
||||||
return pd.read_csv(path, encoding=detected_encoding, sep=';')
|
df = pd.read_csv(path, encoding=detected_encoding, sep=';')
|
||||||
|
df = check_columns(df)
|
||||||
|
return df
|
||||||
except pd.errors.ParserError as e:
|
except pd.errors.ParserError as e:
|
||||||
print(f"Erneut Fehler in CSV-Datei: {e}")
|
print(f"Erneut Fehler in CSV-Datei: {e}")
|
||||||
print(f"Datei muss manuell geändert werden.")
|
print(f"Datei muss manuell geändert werden.")
|
||||||
|
|
||||||
|
|
||||||
|
# die Spalten benötigen fest definierte Namen, auch in Bezug auf Groß- und Kleinschreibung
|
||||||
|
# häufige Abweichungen automatisch anpassen:
|
||||||
|
def check_columns(data):
|
||||||
|
for column in data.columns:
|
||||||
|
if column == 'Nachname':
|
||||||
|
data = data.rename(columns={'Nachname': 'name'})
|
||||||
|
if column == 'Name':
|
||||||
|
data = data.rename(columns={'Name': 'name'})
|
||||||
|
if column == 'Vorname':
|
||||||
|
data = data.rename(columns={'Vorname': 'vorname'})
|
||||||
|
if column == 'Klasse':
|
||||||
|
data = data.rename(columns={'Klasse': 'klasse'})
|
||||||
|
check_duplicates(data)
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def check_duplicates(df):
|
||||||
|
df['full_name'] = df['name'] + ' ' + df['vorname']
|
||||||
|
|
||||||
|
duplicates = df[df.duplicated('full_name', keep=False)]
|
||||||
|
if not duplicates.empty:
|
||||||
|
print("\nWARNUNG: Duplikate gefunden:")
|
||||||
|
print(duplicates)
|
||||||
|
|
||||||
|
|
||||||
# zum Einlesen der bisherigen Systemdaten
|
# zum Einlesen der bisherigen Systemdaten
|
||||||
def create_dataframe_system(path):
|
def create_dataframe_system(path):
|
||||||
try:
|
try:
|
||||||
return pd.read_csv(path, encoding='utf', sep=';')
|
return pd.read_csv(path, encoding='utf', sep=';')
|
||||||
except pd.errors.ParserError as e:
|
except pd.errors.ParserError as e:
|
||||||
print(f"Fehler beim Einlesen der CSV")
|
print(f"Fehler {e} beim Einlesen der System CSV: {path}")
|
||||||
|
|
||||||
|
|
||||||
# zum Extrahieren von Test- und Funktionsusern
|
# zum Extrahieren von Test- und Funktionsusern
|
||||||
@@ -57,4 +86,11 @@ def contains_search_term(row, key):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
# Prüfen, ob erhöhte Quotas vergeben wurden
|
||||||
|
def check_quotas(data, mail_quota, ox_quota):
|
||||||
|
print("\n Quota Check:")
|
||||||
|
mail_quota_exceptions = data[data['mailUserQuota'] > mail_quota]
|
||||||
|
print(mail_quota_exceptions.drop(columns=['klasse', 'schuelerid', 'oxContext', 'oxUserQuota']))
|
||||||
|
ox_quota_exceptions = data[data['oxUserQuota'] > ox_quota]
|
||||||
|
print(ox_quota_exceptions.drop(columns=['klasse', 'schuelerid', 'oxContext', 'mailUserQuota']))
|
||||||
|
return data
|
||||||
|
|||||||
23
src/step2.py
23
src/step2.py
@@ -1,8 +1,9 @@
|
|||||||
|
import numpy as np
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
from Levenshtein import distance
|
from Levenshtein import distance
|
||||||
|
|
||||||
|
|
||||||
def compare_data(new, sys, count_test):
|
def compare_data(new, sys, count_test, path, school):
|
||||||
print(f"\nEinträge in System Liste: {len(sys)}")
|
print(f"\nEinträge in System Liste: {len(sys)}")
|
||||||
print(f"Einträge in Import Liste: {len(new)}")
|
print(f"Einträge in Import Liste: {len(new)}")
|
||||||
|
|
||||||
@@ -11,6 +12,8 @@ def compare_data(new, sys, count_test):
|
|||||||
if bool_class:
|
if bool_class:
|
||||||
if 'index' in new.columns:
|
if 'index' in new.columns:
|
||||||
new = new.drop('index', axis=1)
|
new = new.drop('index', axis=1)
|
||||||
|
unique_classes(new, school)
|
||||||
|
unique_classes(sys, school)
|
||||||
sys = sys.drop(columns=['klasse'])
|
sys = sys.drop(columns=['klasse'])
|
||||||
merged_df = pd.merge(new[['name', 'vorname', 'klasse']], sys, on=['name', 'vorname'], how='outer', indicator=True)
|
merged_df = pd.merge(new[['name', 'vorname', 'klasse']], sys, on=['name', 'vorname'], how='outer', indicator=True)
|
||||||
matches = pd.merge(new, sys, on=['name', 'vorname'])
|
matches = pd.merge(new, sys, on=['name', 'vorname'])
|
||||||
@@ -23,7 +26,7 @@ def compare_data(new, sys, count_test):
|
|||||||
only_new = merged_df[merged_df['_merge'] == 'left_only'].drop(columns=['_merge'])
|
only_new = merged_df[merged_df['_merge'] == 'left_only'].drop(columns=['_merge'])
|
||||||
only_sys = merged_df[merged_df['_merge'] == 'right_only'].drop(columns=['_merge'])
|
only_sys = merged_df[merged_df['_merge'] == 'right_only'].drop(columns=['_merge'])
|
||||||
|
|
||||||
print_status(matches, only_new, only_sys, count_test)
|
print_status(matches, only_new, only_sys, count_test, path)
|
||||||
search_typos(only_new[['name', 'vorname']], only_sys[['name', 'vorname']])
|
search_typos(only_new[['name', 'vorname']], only_sys[['name', 'vorname']])
|
||||||
|
|
||||||
return matches, only_new
|
return matches, only_new
|
||||||
@@ -44,7 +47,21 @@ def search_typos(new, sys):
|
|||||||
print('Mögliche Tippfehler: keine Fehler gefunden!')
|
print('Mögliche Tippfehler: keine Fehler gefunden!')
|
||||||
|
|
||||||
|
|
||||||
def print_status(matches, new, old, count_test):
|
def unique_classes(df, school):
|
||||||
|
df['klasse'] = df['klasse'].str.split(',')
|
||||||
|
df = df.explode('klasse')
|
||||||
|
eindeutige_klassen = df['klasse'].unique()
|
||||||
|
with open(f'./Data/{school}/gen_klassen.txt', 'a') as file:
|
||||||
|
file.write(np.array_str(eindeutige_klassen))
|
||||||
|
# print(eindeutige_klassen)
|
||||||
|
|
||||||
|
|
||||||
|
def print_status(matches, new, old, count_test, path):
|
||||||
print("\nAnzahl neuer Nutzer:", len(new))
|
print("\nAnzahl neuer Nutzer:", len(new))
|
||||||
print("Anzahl Übereinstimmungen:", len(matches) + count_test)
|
print("Anzahl Übereinstimmungen:", len(matches) + count_test)
|
||||||
print("Anzahl veralteter Nutzer:", len(old) - count_test)
|
print("Anzahl veralteter Nutzer:", len(old) - count_test)
|
||||||
|
with pd.ExcelWriter(path, engine='openpyxl') as writer:
|
||||||
|
|
||||||
|
matches.to_excel(writer, sheet_name='Matches', index=False)
|
||||||
|
new.to_excel(writer, sheet_name='Neu', index=False)
|
||||||
|
old.to_excel(writer, sheet_name='Alt', index=False)
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ def create_uuid():
|
|||||||
|
|
||||||
def add_hl_tag(sid, row):
|
def add_hl_tag(sid, row):
|
||||||
klasse = str(row['klasse'])
|
klasse = str(row['klasse'])
|
||||||
klasse = klasse.lstrip('0').lower()
|
klasse = klasse.lstrip('[').rstrip(']').replace('\'', '')
|
||||||
|
# klasse = klasse.lstrip('0').lower()
|
||||||
if klasse != 'nan':
|
if klasse != 'nan':
|
||||||
return sid + '-' + klasse
|
return sid + '-' + klasse
|
||||||
|
|
||||||
@@ -34,6 +35,7 @@ def add_school_data(df, sid, ox_context, mail_quota, ox_quota):
|
|||||||
def create_output_list(name, new, matched, dev, sid, oxc, mail_q, oxq, testuser, out_path):
|
def create_output_list(name, new, matched, dev, sid, oxc, mail_q, oxq, testuser, out_path):
|
||||||
df = merch_uuids(new, matched, dev)
|
df = merch_uuids(new, matched, dev)
|
||||||
df = add_school_data(df, sid, oxc, mail_q, oxq)
|
df = add_school_data(df, sid, oxc, mail_q, oxq)
|
||||||
|
# print(df.drop(columns=['schuelerid', 'oxContext', 'mailUserQuota', 'full_name', 'oxUserQuota']))
|
||||||
df = pd.concat([df, testuser], ignore_index=True)
|
df = pd.concat([df, testuser], ignore_index=True)
|
||||||
df = df[['name', 'vorname', 'klasse', 'schuelerid', 'mailUserQuota', 'oxUserQuota', 'oxContext']]
|
df = df[['name', 'vorname', 'klasse', 'schuelerid', 'mailUserQuota', 'oxUserQuota', 'oxContext']]
|
||||||
print(f"\n{len(testuser)} Testuser angefügt - {len(df)} Einträge in {name} Liste")
|
print(f"\n{len(testuser)} Testuser angefügt - {len(df)} Einträge in {name} Liste")
|
||||||
|
|||||||
Reference in New Issue
Block a user