python files verschoben

This commit is contained in:
2023-06-06 16:35:41 +02:00
parent 193fa1d277
commit 2eeac20acd
6 changed files with 9256 additions and 1 deletions
+2 -1
View File
@@ -1,2 +1,3 @@
call ecalc_setenv.bat
python %ECALC_LIB%\calc_site.py --infile=jayjay.cfg
python %ECALC_LIB%\calc_site.py --infile=jayjay.cfg --outfile=JayJay_old.xlsx
python %ECALC_LIB%\calc_site.py --infile=jayjay.cfg --config=Sivas_Daten_jayjay.cfg --outfile=JayJay_new.xlsx
+167
View File
@@ -0,0 +1,167 @@
import pandas as pd
import configparser
import os.path
import argparse
"""
Erstellung einer Excel-Datei mit aktuellen Preisen aus Sivas ist leicht möglich.
Diese soll in einer config-Datei für die Berechnung der rieter-eKalkulation verwendet werden.
Den Parametern der rieter_ekalk werden die entsprechenden Sivas-Nummern zugewiesen, und damit die aktuellen Preise.
Diese Zuordnung von Parametern und ihren aktuellen Preisen wird wieder in eine config-Datei geschrieben, die mit den Preisen der Sivas_Daten.cfg-Datei abzugleichen ist, auf die rieter_ekalk zugreift.
"""
class Kosten():
"""
Liest die Sivas-Excel-Liste ein und schreibt eine neue config Datei mit den aktuellen Preisen der in rieter-ekalk verwendeten Sivas-IDs.
"""
def __init__(self, pathNew="Zuordnung_Teilenummern.cfg", pathOld="Sivas_Daten.cfg", sivasData="grid_export.xlsx"):
"""
:param pathNew: cfg-Datei, die den Bauteilen ihre Sivas-Nummern zuweist z.B. "schaltschrankgehaeuse_b2x800_zubehoer = 790821101"
:param pathOld: cfg-Datei, die in rieter_ekalk verwendet wird und den Bauteilen Preise zuweist z.B. "schaltschrankgehaeuse_b2x800_zubehoer = 4663.45"
:param sivasData: Excel-Datei mit Sivas-Nummern und entsprechenden Preisen, Überschrift: Teilenummer, Laufende Materialkosten
"""
df = pd.read_excel(sivasData, header=0, index_col=0, usecols=["Teilenummer", "Laufende Materialkosten" ])
self._kosten = df.to_dict()
self._given = True
if os.path.exists(pathNew):
self._zuordnung = configparser.ConfigParser(inline_comment_prefixes="#")
self._zuordnung.read_file(open(pathNew))
else:
self._given = False
self._zuordnung = None
self._default = configparser.ConfigParser(inline_comment_prefixes="#")
self._default.read_file(open(pathOld))
# wird verwendet, um die Werte der alten config zu speichern
self._HW_Einzelpreise = None
def exists(self):
return self._given
def getNewPricesAsDict(self, not_found_keys):
"""
Gibt die neuen Preise als Dict zurück.
:param not_found_keys: Dict von Bauteilen, denen eine Nummer zugeordnet ist, die in Sivas nicht existiert z.B. {'schaltschrankgehaeuse_b1x800_zubehoer': '----'}
"""
faktoren = self.getZuordnungTeilenummernAsDict("Faktoren")
newDict = {}
for key, val in self.getZuordnungTeilenummernAsDict("HW_Einzelpreise").items():
number = val.strip()
self.getPriceFromNumber(key, number, newDict, not_found_keys)
if "+" in number:
del not_found_keys[key]
split_sivas_ids = number.split('+')
self.getPriceFromAddedNumbers(key, split_sivas_ids, newDict, not_found_keys)
if key in faktoren:
newDict[key] *= float(faktoren[key])
return newDict
def getPriceFromAddedNumbers(self, key, split_sivas_ids, newDict, not_found_keys):
"""
Trägt die Zuordnung Bauteil:Gesamtpreis in das newDict Dictionary ein, wenn das Bauteil mehrere Sivas-Nummern beinhaltet.
Ist die Nummer eines Summanden nicht in Sivas enthalten, wird er in das Dict "not_found_keys" eingetragen.
:param split_sivas_ids: Liste von Sivas IDs, die addiert werden z.B. [' 827072204', ' 721000041']
:param key: Name z.B. "anlagenrechner_ohne_bildschirm"
:param newDict: z.B. {'schaltschrankgehaeuse_b2x800_zubehoer':9490.23, ...}
:param not_found_keys: Dict von Bauteilen, denen eine Nummer zugeordnet ist, die in Sivas nicht existiert z.B. {'schaltschrankgehaeuse_b1x800_zubehoer': '----'}
"""
price = 0
for summand in split_sivas_ids:
summand = summand.strip()
# summand: einzelner Summand z.B. '827072204'
if summand in self._kosten["Laufende Materialkosten"]:
cost = self._kosten["Laufende Materialkosten"][summand]
# cost: Einzelpreis eines Summanden [€]
if type(cost) is type(int) or type(float):
price += cost
# price: Gesamtpreis
newDict.update({key: price})
else:
not_found_keys.update({key:summand})
def getPriceFromNumber(self, key, number, newDict, not_found_keys):
"""
Trägt die Zuordnung Bauteil:Gesamtpreis in das newDict Dictionary ein, wenn das Bauteil eine Sivas-Nummer beinhaltet.
In Sivas nicht existierende Nummern werden in das Dict "not_found_keys" zurückgegeben.
:param key: Name z.B. "anlagenrechner_ohne_bildschirm"
:param number: Sivas Nummer zum key z.B. '827072204'
:param newDict: z.B. {'schaltschrankgehaeuse_b2x800_zubehoer':9490.23, ...}
:param not_found_keys: Dict von Bauteilen, denen eine Nummer zugeordnet ist, die in Sivas nicht existiert z.B. {'schaltschrankgehaeuse_b1x800_zubehoer': '----'}
"""
if number in self._kosten["Laufende Materialkosten"]:
price = self._kosten["Laufende Materialkosten"][number]
if price is int or float:
newDict.update({key: price})
else:
not_found_keys.update({key:number})
def getDefaultDictAsFloat(self, section_name):
res = dict()
for key, val in self._default.items(section_name):
res[key] = float(val)
return res
def getZuordnungTeilenummernAsDict(self, section_name):
res = dict()
for key, val in self._zuordnung.items(section_name):
res[key] = val
return res
def writeNewConfig(self, name='Sivas_Abgleich.cfg'):
config = configparser.ConfigParser()
config["HW_Einzelpreise"] = latest_costs
config["Preise durch Sivas nicht ermittelbar"] = not_found_in_sivas
with open(name, 'w') as configfile:
config.write(configfile)
def writePriceIncrements(self, name='Preis_Increments.xlsx'):
not_found_in_sivas = dict()
latest_costs = self.getNewPricesAsDict(not_found_in_sivas)
sivas_numbers = list()
old_prices = list()
new_prices = list()
for sivas_number in latest_costs.keys():
sivas_numbers.append(sivas_number)
old_prices.append(self.getDefaultDictAsFloat("HW_Einzelpreise").get(sivas_number))
new_prices.append(latest_costs.get(sivas_number))
data = {"Sivas-Nummern":sivas_numbers, "Alte Preise":old_prices, "Neue Preise":new_prices}
df = pd.DataFrame.from_dict(data)
df.to_excel(name, sheet_name="Preisänderungen", index_label="Sivas-Nummern")
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='calculation of a system according to Bös', prog='ecalc')
parser.add_argument('-o', '--outfile', action='store', help='name of the output excel file', default="Preis_Increments.xlsx")
args = parser.parse_args()
zuordCfgFilePath = os.path.join(os.environ.get('ECALC_CFG'), "Zuordnung_Teilenummern.cfg")
sivasCfgFilePath = os.path.join(os.environ.get('ECALC_CFG'), "Sivas_Daten.cfg")
gridExportFilePath = os.path.join(os.environ.get('ECALC_CFG'), "grid_export.xlsx")
if not os.path.isfile(zuordCfgFilePath):
print("no Zuordnung_Teilenummern.cfg in ECALC_CFG")
if not os.path.isfile(sivasCfgFilePath):
print("no Sivas_Daten.cfg in ECALC_CFG")
if not os.path.isfile(gridExportFilePath):
print("no grid_export.xlsx with prices from SIVAS in ECALC_CFG")
# lies die alten config und die Excel-Liste mit den Sivas-Daten
costs = Kosten(zuordCfgFilePath, sivasCfgFilePath, gridExportFilePath)
not_found_in_sivas = dict()
latest_costs = costs.getNewPricesAsDict(not_found_in_sivas)
# schreibe die neue config mit den aktuellen Preisen
outCfg = os.path.join(os.environ.get('ECALC_WORK'), "Sivas_Abgleich.cfg")
costs.writeNewConfig(outCfg)
# schreibe die Preisänderungen in eine Excel-Datei
outPath = os.path.join(os.environ.get('ECALC_WORK'), args.outfile)
costs.writePriceIncrements(outPath)
+158
View File
@@ -0,0 +1,158 @@
import rieter_ekalk as rek
import pandas as pd
import argparse
import os
import configparser
class cfg():
"""
Liest die config-Datei ein, in der Stückpreise und Zeiteinheiten pro Bauteil wie in der rieter_ekalk Excel-Datei verwendet angegeben sind, und schreibt sie in ein Dictionary.
"""
def __init__(self, path="Sivas_Daten.cfg"):
"""
:param path: Die config-Datei, in der Stückpreise und Zeiteinheiten der jeweiligen Bauteile aufgelistet sind z.B.[HW_Einzelpreise]
# Schaltschrank Einzelpreis
schaltschrankgehaeuse_b1x800_zubehoer = 2000
"""
self._hasConfig = True
if os.path.exists(path):
self._cfg = configparser.ConfigParser(inline_comment_prefixes="#")
self._cfg.optionxform = str
self._cfg.read_file(open(path))
else:
self._hasConfig = False
self._cfg = None
def exists(self):
return self._hasConfig
def isfloat(self, num):
try:
float(num)
return True
except ValueError:
return False
def getTypedDict(self, section:str):
"""
Schreibt die Zuordnungen von Bauteil:Stückpreis/Zeiteinheit (je nach gewählter Überschrift) aus der config-Datei in ein Dictionary.
:param section: Überschrift in der config-Datei z.B. "HW_Einzelpreise"
"""
if section not in self._cfg.sections():
return dict()
res = dict()
for key, val in self._cfg.items(section):
if val.lower() in ['true']:
res[key] =True
elif val.lower() in ['false']:
res[key] =False
elif val.startswith("-"):
res[key] = float(val)
elif self.isfloat(val):
res[key] = float(val)
else:
res[key] = val
return res
def run_calc(infile, outfile, SivasConfig):
infileCfg = cfg(infile)
Anzahl_MG = infileCfg.getTypedDict("allgemein")
rsm_direct_eingabe = infileCfg.getTypedDict("rsm_direct")
rsm_fa_eingabe = infileCfg.getTypedDict("rsm_fa")
flyer_f40_eingabe = infileCfg.getTypedDict("flyer_f40")
neuenhauser_eingabe = infileCfg.getTypedDict("neuenhauser")
flyer_eingabe = infileCfg.getTypedDict("flyer")
verbindungsstrecken_w_eingabe = infileCfg.getTypedDict("verbindungsstrecken_w")
puffer_eingabe = infileCfg.getTypedDict("puffer")
turm_eingabe = infileCfg.getTypedDict("turm")
mg = rek.MG(Anzahl_MG,
rsm_direct=rsm_direct_eingabe,
rsm_fa=rsm_fa_eingabe,
flyer_f40=flyer_f40_eingabe,
neuenhauser=neuenhauser_eingabe,
flyer=flyer_eingabe,
verbindungsstrecken_w=verbindungsstrecken_w_eingabe,
puffer=puffer_eingabe,
turm=turm_eingabe)
anStr = SivasConfig.getTypedDict("Antriebsstrom")
cosPhi = SivasConfig.getTypedDict("cos phi")
al = rek.Anschlussl(anStr, cosPhi)
Anzahl_AL ={}
al.calc(Anzahl_AL, mg)
# self.assertEqual(al._ANZAHL.get("Anzahl_Motor"), 48)
# self.assertAlmostEqual(al._ANZAHL.get("Summe_Strom_Motor"), 26.4)
# self.assertAlmostEqual(al._ANZAHL.get("Summe_Strom_Motor_SPS_Peripherie"), 29.4)
# self.assertAlmostEqual(al._ANZAHL.get("GZF"), 16.2)
# self.assertAlmostEqual(al._ANZAHL.get("Res"), 1.62)
# self.assertAlmostEqual(al._ANZAHL.get("Gesamtstrom"), 17.82)
# self.assertAlmostEqual(al._Anschlussspannung, 400)
# self.assertAlmostEqual(al._ANZAHL.get("Leistung"), 12.345696)
# self.assertAlmostEqual(al._ANZAHL.get("Gesamtanschlussleistung"), 13)
Anzahl_EAS = infileCfg.getTypedDict("EAS")
eas = rek.EA(Anzahl_EAS, mg)
Anzahl_HW = infileCfg.getTypedDict("HW")
hwep = SivasConfig.getTypedDict("HW_Einzelpreise")
hwhp = SivasConfig.getTypedDict("HW_Zeiten Hardwareplanung")
hwzew = SivasConfig.getTypedDict("HW_Zeiten Elektro-Werkstatt")
hw = rek.HW(hwep, hwhp, hwzew)
hw.calc(Anzahl_HW, mg, eas)
emoz = SivasConfig.getTypedDict("Elektro-Montagezeiten")
emo = rek.EMO(emoz)
emo.calc(eas, hw, mg)
Anzahl_DL = infileCfg.getTypedDict("DL")
dl = rek.Dienstleistung(Anzahl_DL, hw)
Anzahl_Ergebnis = infileCfg.getTypedDict("Ergebnis")
kph = SivasConfig.getTypedDict("Kosten pro h")
erg = rek.Ergebnis(kph)
erg.calc(Anzahl_Ergebnis, hw, dl, emo)
summary = erg.summary_costs(hw)
df = pd.DataFrame.from_dict(data=summary, orient='index', columns=['Aufwand'])
df.to_excel(outfile, sheet_name="Kostenaufstellung")
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='calculation of a system according to Bös', prog='ecalc')
parser.add_argument('-i', '--infile', action='store', help='name of the input file', default="jayjay.cfg")
parser.add_argument('-o', '--outfile', action='store', help='name of the output .xlsx file. If none given, name of the input file is used.')
parser.add_argument('-c', '--config', action='store', help='name of the config file inside of cfg folder to use. Default is Sivas_Daten.cfg', default="Sivas_Daten.cfg")
args = parser.parse_args()
sivasCfgFilePath = os.path.join(os.environ.get('ECALC_CFG'), args.config)
RieterConfig = cfg(sivasCfgFilePath)
inFilePath = os.path.join(os.environ.get('ECALC_WORK'), args.infile)
if os.path.isfile(inFilePath):
if args.outfile:
outPath = os.path.join(os.environ.get('ECALC_WORK'), args.outfile)
else:
(fname, ext) = os.path.splitext(args.infile)
outPath = os.path.join(os.environ.get('ECALC_WORK'), fname + '.xlsx')
run_calc(inFilePath, outPath, RieterConfig)
else:
print("no such file in ECALC_WORK")
# os.environ.get('ECALC_BIN')
# os.environ.get('ECALC_WORK')
# os.environ.get('ECALC_CFG')
# os.environ.get('ECALC_LIB')
+2716
View File
File diff suppressed because it is too large Load Diff
+2199
View File
File diff suppressed because it is too large Load Diff
+4014
View File
File diff suppressed because it is too large Load Diff