From 1a1271c7e0e5b46177156bfae07d4070197f93e2 Mon Sep 17 00:00:00 2001 From: Filip Krumpe Date: Thu, 13 Jan 2022 21:03:29 +0100 Subject: [PATCH] adopt to new spielbergerscripts version --- Produktionsplanung.ipynb | 2426 ++++++++++++++++++++------------------ 1 file changed, 1250 insertions(+), 1176 deletions(-) diff --git a/Produktionsplanung.ipynb b/Produktionsplanung.ipynb index fa8ea17..0de3fb2 100644 --- a/Produktionsplanung.ipynb +++ b/Produktionsplanung.ipynb @@ -3,1353 +3,1427 @@ { "cell_type": "code", "execution_count": null, - "source": [ - "import re\r\n", - "import math\r\n", - "\r\n", - "from dataclasses import dataclass\r\n", - "\r\n", - "from copy import copy\r\n", - "\r\n", - "from openpyxl import load_workbook, Workbook\r\n", - "from openpyxl.utils import datetime\r\n", - "from openpyxl.styles import Color, PatternFill\r\n", - "from openpyxl.worksheet.table import Table\r\n", - "\r\n", - "from spielbergerscripts.spielbergerscripts.storageunit import Product, Bundle\r\n", - "from spielbergerscripts.spielbergerscripts.connector import IBMConnector" - ], + "metadata": {}, "outputs": [], - "metadata": {} + "source": [ + "import re\n", + "import math\n", + "import datetime\n", + "\n", + "from dataclasses import dataclass\n", + "\n", + "from copy import copy\n", + "\n", + "from openpyxl import load_workbook, Workbook\n", + "from openpyxl.styles import Color, PatternFill\n", + "from openpyxl.worksheet.table import Table\n", + "\n", + "from spielbergerscripts.primitives.product import Product, Bundle\n", + "from spielbergerscripts.connector import IBMConnector" + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ - "# define some colors\r\n", - "\r\n", - "yellow = Color(rgb='FFFF00')\r\n", - "red = Color(rgb='E6B8B7')\r\n", - "orange = Color(rgb='FCD5B4')\r\n", - "purple = Color(rgb='CCC0DA')\r\n", + "# define some colors\n", + "\n", + "yellow = Color(rgb='FFFF00')\n", + "red = Color(rgb='E6B8B7')\n", + "orange = Color(rgb='FCD5B4')\n", + "purple = Color(rgb='CCC0DA')\n", "blue = Color(rgb='B8CCE4')" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ - "# classes Abpackung, DispoBedarf, Leistungsdaten, Umbau, Vorlage\r\n", - "\r\n", - "@dataclass\r\n", - "class Abpackung:\r\n", - " artikelNummer: int # ArtNr\r\n", - " abpackMenge: int # in KG\r\n", - " bemerkung: str\r\n", - " planPos: int # Wochenplannummer\r\n", - " bem_ek: str # Bemerkung Einkauf\r\n", - " roh1: str # Rohstoff 1\r\n", - " roh1_bes: str # Rohstoff 1 Bestand\r\n", - " roh2: str # Rohstoff 2\r\n", - " roh2_bes: str # Rohstoff 2 Bestand\r\n", - "\r\n", - " def anzBeutel(self, bundles):\r\n", - " gg = bundles[self.artikelNummer]\r\n", - " return int((self.abpackMenge * 1000) / gg.bagWeight)\r\n", - "\r\n", - " def anzGebinde(self, bundles):\r\n", - " gg = bundles[self.artikelNummer]\r\n", - " return int(self.anzBeutel(bundles) / gg.nbrBags)\r\n", - "\r\n", - "@dataclass\r\n", - "class DispoBedarf:\r\n", - " artikelNummer: str # ArtNr\r\n", - " palettenziel: int # Menge / Soll Palette\r\n", - " bestandL00: int # Cha BES00\r\n", - " bestandL01: int # Cha BES00\r\n", - " bestandL05: int # Cha BES05\r\n", - " auftragsBestand:int # Auf Bes\r\n", - " bestellBestand: int # Best Bes\r\n", - " durchschnitt: int # Durchschnitt Bestellung pro Woche\r\n", - " tuetenAnz: int # Anzahl Tüten Lager + HLB\r\n", - " bem_ek: str # Bemerkung Einkauf\r\n", - " roh1: str # Rohstoff 1\r\n", - " roh1_bes: str # Rohstoff 1 Bestand\r\n", - " roh2: str # Rohstoff 2\r\n", - " roh2_bes: str # Rohstoff 2 Bestand\r\n", - "\r\n", - " def bestandFrei(self):\r\n", - " return self.bestandL00 + self.bestandL05 + self.bestellBestand - self.auftragsBestand\r\n", - "\r\n", - " def reichweite(self, prodNeu = 0):\r\n", - " return (self.bestandFrei() + prodNeu) / self.durchschnitt\r\n", - "\r\n", - " def reichweiteNeu(self, abpackDict, prodDict):\r\n", - " abp = abpackDict.get(self.artikelNummer, None)\r\n", - " if abp is None:\r\n", - " return self.reichweite()\r\n", - "\r\n", - " return self.reichweite(abp.anzBeutel(prodDict))\r\n", - "\r\n", - "@dataclass\r\n", - "class Leistungsdaten:\r\n", - " artikelNummer: str\r\n", - " leistung: dict # Beutel / h pro Packerei (Pack1, Pack2, Pack3, Pack4)\r\n", - " modi: dict # Produktionsmodus pro Packerei\r\n", - " kurzBez: str\r\n", - " gebindeGr: Bundle\r\n", - " palettenMenge: int\r\n", - " muehle: bool\r\n", - " muehleMisch: bool\r\n", - " rezept: bool\r\n", - " gfProd: bool\r\n", - " duezi: bool\r\n", - "\r\n", - "\r\n", - "@dataclass\r\n", - "class Umbauzeiten:\r\n", - " pack: str\r\n", - " modi: set\r\n", - " umbau: dict\r\n", - "\r\n", - "@dataclass\r\n", - "class PackereiVorlage:\r\n", - " packerei: str\r\n", - " beginn: datetime.datetime\r\n", + "# classes Abpackung, DispoBedarf, Leistungsdaten, Umbau, Vorlage\n", + "\n", + "@dataclass\n", + "class Abpackung:\n", + " artikelNummer: int # ArtNr\n", + " abpackMenge: int # in KG\n", + " bemerkung: str\n", + " planPos: int # Wochenplannummer\n", + " bem_ek: str # Bemerkung Einkauf\n", + " roh1: str # Rohstoff 1\n", + " roh1_bes: str # Rohstoff 1 Bestand\n", + " roh2: str # Rohstoff 2\n", + " roh2_bes: str # Rohstoff 2 Bestand\n", + "\n", + " def anzBeutel(self, bundles):\n", + " gg = bundles[self.artikelNummer]\n", + " return int((self.abpackMenge * 1000) / gg.bagWeight)\n", + "\n", + " def anzGebinde(self, bundles):\n", + " gg = bundles[self.artikelNummer]\n", + " return int(self.anzBeutel(bundles) / gg.nbrBags)\n", + "\n", + "@dataclass\n", + "class MischBedarf:\n", + " artikelNummer: int # ArtNr\n", + " abpackMenge: int # in KG\n", + " kw_reich: float # KW REICH\n", + " bem_ek: str # Bemerkung Einkauf\n", + " roh1: str # Rohstoff 1\n", + " roh1_bes: str # Rohstoff 1 Bestand\n", + " roh2: str # Rohstoff 2\n", + " roh2_bes: str # Rohstoff 2 Bestand\n", + "\n", + "@dataclass\n", + "class DispoBedarf:\n", + " artikelNummer: str # ArtNr\n", + " palettenziel: int # Menge / Soll Palette\n", + " bestandL00: int # Cha BES00\n", + " bestandL01: int # Cha BES00\n", + " bestandL05: int # Cha BES05\n", + " auftragsBestand:int # Auf Bes\n", + " bestellBestand: int # Best Bes\n", + " durchschnitt: int # Durchschnitt Bestellung pro Woche\n", + " tuetenAnz: int # Anzahl Tüten Lager + HLB\n", + " bem_ek: str # Bemerkung Einkauf\n", + " roh1: str # Rohstoff 1\n", + " roh1_bes: str # Rohstoff 1 Bestand\n", + " roh2: str # Rohstoff 2\n", + " roh2_bes: str # Rohstoff 2 Bestand\n", + "\n", + " def bestandFrei(self):\n", + " return self.bestandL00 + self.bestandL05 + self.bestellBestand - self.auftragsBestand\n", + "\n", + " def reichweite(self, prodNeu = 0):\n", + " return (self.bestandFrei() + prodNeu) / self.durchschnitt\n", + "\n", + " def reichweiteNeu(self, abpackDict, prodDict):\n", + " abp = abpackDict.get(self.artikelNummer, None)\n", + " if abp is None:\n", + " return self.reichweite()\n", + "\n", + " return self.reichweite(abp.anzBeutel(prodDict))\n", + "\n", + "@dataclass\n", + "class Leistungsdaten:\n", + " artikelNummer: str\n", + " leistung: dict # Beutel / h pro Packerei (Pack1, Pack2, Pack3, Pack4)\n", + " modi: dict # Produktionsmodus pro Packerei\n", + " kurzBez: str\n", + " gebindeGr: Bundle\n", + " palettenMenge: int\n", + " muehle: bool\n", + " muehleMisch: bool\n", + " rezept: bool\n", + " gfProd: bool\n", + " duezi: bool\n", + "\n", + "\n", + "@dataclass\n", + "class Umbauzeiten:\n", + " pack: str\n", + " modi: set\n", + " umbau: dict\n", + "\n", + "@dataclass\n", + "class PackereiVorlage:\n", + " packerei: str\n", + " beginn: datetime.datetime\n", " vorlage: str" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, - "source": [ - "# read Vorlage, Leistugnsdaten, Umbauzeiten, Stammdaten, Leistungsdaten\r\n", - "\r\n", - "def packVorlage(sheet):\r\n", - " vorlage = dict()\r\n", - " vorlage[\"Pack1\"] = PackereiVorlage(\r\n", - " packerei = sheet['A3'].value,\r\n", - " beginn = sheet['B3'].value,\r\n", - " vorlage = sheet['C3'].value,\r\n", - " )\r\n", - " vorlage[\"Pack2\"] = PackereiVorlage (\r\n", - " packerei = sheet['A4'].value,\r\n", - " beginn = sheet['B4'].value,\r\n", - " vorlage = sheet['C4'].value,\r\n", - " )\r\n", - " vorlage[\"Pack3\"] = PackereiVorlage (\r\n", - " packerei = sheet['A5'].value,\r\n", - " beginn = sheet['B5'].value,\r\n", - " vorlage = sheet['C5'].value,\r\n", - " )\r\n", - " vorlage[\"Pack4\"] = PackereiVorlage (\r\n", - " packerei = sheet['A6'].value,\r\n", - " beginn = sheet['B6'].value,\r\n", - " vorlage = sheet['C6'].value,\r\n", - " )\r\n", - "\r\n", - " return vorlage\r\n", - "\r\n", - "def getPackLeistung(artikelNummer):\r\n", - " return LEISTUNGS_DICT.get(artikelNummer, LEISTUNGS_DICT[\"000000\"]) \r\n", - "\r\n", - "def getWechsel(modus, new_modus, pack):\r\n", - " tWechsel = PROD_STAMM[pack].umbau.get((modus, new_modus), None)\r\n", - " if tWechsel is None:\r\n", - " return 20\r\n", - " else:\r\n", - " return tWechsel\r\n", - "\r\n", - "def shortName(artikelNummer):\r\n", - " return getPackLeistung(artikelNummer).kurzBez\r\n", - "\r\n", - "def beutelProH(artikelNummer, packerei):\r\n", - " return getPackLeistung(artikelNummer).leistung[packerei]\r\n", - "\r\n", - "def readProdStamm(sheet, pack, offset):\r\n", - " modi = []\r\n", - " count = 0\r\n", - " while True:\r\n", - " c = sheet.cell(row=offset + 2 + count, column = 2).value\r\n", - " if c is None:\r\n", - " break\r\n", - " modi.append(c)\r\n", - " count += 1\r\n", - " umbau = dict()\r\n", - " for idxI, modI in enumerate(modi):\r\n", - " for idxJ, modJ in enumerate(modi):\r\n", - " umbau[modI, modJ] = int(sheet.cell(row=offset + 2 + idxJ, column=6+idxI).value)\r\n", - " return Umbauzeiten(\r\n", - " pack,\r\n", - " modi,\r\n", - " umbau\r\n", - " )\r\n", - "\r\n", - "def produktionStammdaten(sheet):\r\n", - " return {\r\n", - " \"Pack1\": readProdStamm(sheet, \"Pack1\", 1),\r\n", - " \"Pack2\": readProdStamm(sheet, \"Pack2\", 11),\r\n", - " \"Pack3\": readProdStamm(sheet, \"Pack3\", 30),\r\n", - " \"Pack4\": readProdStamm(sheet, \"Pack4\", 36),\r\n", - " }\r\n", - "\r\n", - "def isSet(field):\r\n", - " if field is None:\r\n", - " return False\r\n", - " if field != 1:\r\n", - " return False\r\n", - " return True\r\n", - "\r\n", - "def packLeistung(sheet):\r\n", - " leistungs_dict = {}\r\n", - " for row in sheet.iter_rows(min_row=3, max_row=len(sheet['A']), max_col=18, values_only=True):\r\n", - " if row[0] is None:\r\n", - " continue\r\n", - " l = Leistungsdaten(\r\n", - " artikelNummer=row[0],\r\n", - " leistung={\r\n", - " \"Pack1\": int(row[1] if not (row[1] is None or row[1] == \"#N/A\") else 2000),\r\n", - " \"Pack2\": int(row[3] if not (row[3] is None or row[3] == \"#N/A\") else 1000),\r\n", - " \"Pack3\": int(row[5] if not (row[5] is None or row[5] == \"#N/A\") else 800),\r\n", - " \"Pack4\": int(row[7] if not (row[7] is None or row[7] == \"#N/A\") else 60)\r\n", - " },\r\n", - " modi = {\r\n", - " \"Pack1\": row[2],\r\n", - " \"Pack2\": row[4],\r\n", - " \"Pack3\": row[6],\r\n", - " \"Pack4\": row[8]\r\n", - " },\r\n", - " kurzBez=row[9],\r\n", - " gebindeGr=Bundle.fromString(row[10]),\r\n", - " palettenMenge=int(row[11]),\r\n", - " muehle = isSet(row[13]),\r\n", - " muehleMisch = isSet(row[14]),\r\n", - " rezept = isSet(row[15]),\r\n", - " gfProd = isSet(row[16]),\r\n", - " duezi = isSet(row[17])\r\n", - " )\r\n", - " leistungs_dict[l.artikelNummer] = l\r\n", - "\r\n", - " return leistungs_dict" - ], - "outputs": [], "metadata": { "tags": [] - } - }, - { - "cell_type": "code", - "execution_count": null, - "source": [ - "# read Dispo\r\n", - "\r\n", - "def readDispo(sheet):\r\n", - " DISPO_DICT = {}\r\n", - " ABPACK_DICT = {}\r\n", - " GEB_GROESSE = {}\r\n", - " HEADER = True\r\n", - " for row in sheet.rows:\r\n", - " if HEADER: # skip the header lines\r\n", - " if row[0].value == \"ARTNR\":\r\n", - " HEADER = False\r\n", - " continue\r\n", - " if row[0].value is None:\r\n", - " break\r\n", - "\r\n", - " d = DispoBedarf(\r\n", - " artikelNummer=row[0].value,\r\n", - " palettenziel=row[4].value,\r\n", - " bestandL00=row[5].value,\r\n", - " bestandL01=row[6].value,\r\n", - " bestandL05=row[7].value,\r\n", - " auftragsBestand=row[8].value,\r\n", - " bestellBestand=row[15].value,\r\n", - " durchschnitt=row[17].value,\r\n", - " tuetenAnz= 0 if row[24].value is None else int(float(row[24].value)*1000),\r\n", - " roh1 = row[18].value,\r\n", - " roh1_bes = row[20].value,\r\n", - " roh2 = row[21].value,\r\n", - " roh2_bes = row[22].value,\r\n", - " bem_ek = row[23].value\r\n", - " )\r\n", - "\r\n", - " g = Bundle.fromString(row[2].value)\r\n", - "\r\n", - " DISPO_DICT[d.artikelNummer] = d\r\n", - " GEB_GROESSE[d.artikelNummer] = g\r\n", - "\r\n", - " if not (row[25].value is None):\r\n", - " a = Abpackung(\r\n", - " artikelNummer=d.artikelNummer,\r\n", - " abpackMenge=int(row[25].value),\r\n", - " bemerkung=\"\",\r\n", - " planPos= 999 if row[29].value is None else int(int(row[29].value)),\r\n", - " roh1 = row[18].value,\r\n", - " roh1_bes = row[20].value,\r\n", - " roh2 = row[21].value,\r\n", - " roh2_bes = row[22].value,\r\n", - " bem_ek = row[23].value\r\n", - " )\r\n", - "\r\n", - " ABPACK_DICT[d.artikelNummer]=a\r\n", - "\r\n", - " return DISPO_DICT, ABPACK_DICT, GEB_GROESSE" - ], + }, "outputs": [], - "metadata": {} + "source": [ + "# read Vorlage, Leistugnsdaten, Umbauzeiten, Stammdaten, Leistungsdaten\n", + "\n", + "def packVorlage(sheet):\n", + " vorlage = dict()\n", + " vorlage[\"Pack1\"] = PackereiVorlage(\n", + " packerei = sheet['A3'].value,\n", + " beginn = sheet['B3'].value,\n", + " vorlage = sheet['C3'].value,\n", + " )\n", + " vorlage[\"Pack2\"] = PackereiVorlage (\n", + " packerei = sheet['A4'].value,\n", + " beginn = sheet['B4'].value,\n", + " vorlage = sheet['C4'].value,\n", + " )\n", + " vorlage[\"Pack3\"] = PackereiVorlage (\n", + " packerei = sheet['A5'].value,\n", + " beginn = sheet['B5'].value,\n", + " vorlage = sheet['C5'].value,\n", + " )\n", + " vorlage[\"Pack4\"] = PackereiVorlage (\n", + " packerei = sheet['A6'].value,\n", + " beginn = sheet['B6'].value,\n", + " vorlage = sheet['C6'].value,\n", + " )\n", + "\n", + " return vorlage\n", + "\n", + "def getPackLeistung(artikelNummer):\n", + " return LEISTUNGS_DICT.get(artikelNummer, LEISTUNGS_DICT[\"000000\"]) \n", + "\n", + "def getWechsel(modus, new_modus, pack):\n", + " tWechsel = PROD_STAMM[pack].umbau.get((modus, new_modus), None)\n", + " if tWechsel is None:\n", + " return 20\n", + " else:\n", + " return tWechsel\n", + "\n", + "def shortName(artikelNummer):\n", + " return getPackLeistung(artikelNummer).kurzBez\n", + "\n", + "def beutelProH(artikelNummer, packerei):\n", + " return getPackLeistung(artikelNummer).leistung[packerei]\n", + "\n", + "def readProdStamm(sheet, pack, offset):\n", + " modi = []\n", + " count = 0\n", + " while True:\n", + " c = sheet.cell(row=offset + 2 + count, column = 2).value\n", + " if c is None:\n", + " break\n", + " modi.append(c)\n", + " count += 1\n", + " umbau = dict()\n", + " for idxI, modI in enumerate(modi):\n", + " for idxJ, modJ in enumerate(modi):\n", + " umbau[modI, modJ] = int(sheet.cell(row=offset + 2 + idxJ, column=6+idxI).value)\n", + " return Umbauzeiten(\n", + " pack,\n", + " modi,\n", + " umbau\n", + " )\n", + "\n", + "def produktionStammdaten(sheet):\n", + " return {\n", + " \"Pack1\": readProdStamm(sheet, \"Pack1\", 1),\n", + " \"Pack2\": readProdStamm(sheet, \"Pack2\", 11),\n", + " \"Pack3\": readProdStamm(sheet, \"Pack3\", 30),\n", + " \"Pack4\": readProdStamm(sheet, \"Pack4\", 36),\n", + " }\n", + "\n", + "def isSet(field):\n", + " if field is None:\n", + " return False\n", + " if field != 1:\n", + " return False\n", + " return True\n", + "\n", + "def packLeistung(sheet):\n", + " leistungs_dict = {}\n", + " for row in sheet.iter_rows(min_row=3, max_row=len(sheet['A']), max_col=18, values_only=True):\n", + " if row[0] is None:\n", + " continue\n", + " l = Leistungsdaten(\n", + " artikelNummer=row[0],\n", + " leistung={\n", + " \"Pack1\": int(row[1] if not (row[1] is None or row[1] == \"#N/A\") else 2000),\n", + " \"Pack2\": int(row[3] if not (row[3] is None or row[3] == \"#N/A\") else 1000),\n", + " \"Pack3\": int(row[5] if not (row[5] is None or row[5] == \"#N/A\") else 800),\n", + " \"Pack4\": int(row[7] if not (row[7] is None or row[7] == \"#N/A\") else 60)\n", + " },\n", + " modi = {\n", + " \"Pack1\": row[2],\n", + " \"Pack2\": row[4],\n", + " \"Pack3\": row[6],\n", + " \"Pack4\": row[8]\n", + " },\n", + " kurzBez=row[9],\n", + " gebindeGr=Bundle.fromString(row[10]),\n", + " palettenMenge=int(row[11]),\n", + " muehle = isSet(row[13]),\n", + " muehleMisch = isSet(row[14]),\n", + " rezept = isSet(row[15]),\n", + " gfProd = isSet(row[16]),\n", + " duezi = isSet(row[17])\n", + " )\n", + " leistungs_dict[l.artikelNummer] = l\n", + "\n", + " return leistungs_dict" + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ - "# write Schedule\r\n", - "\r\n", - "def writeSchedule(vorlage, abpackDict, prodDict, gebGroesse, pack):\r\n", - " name = f\"Schedule {pack}\"\r\n", - "\r\n", - " sheet = vorlage.copy_worksheet(vorlage[\"Schedule\"])\r\n", - " if name in vorlage.sheetnames:\r\n", - " vorlage.remove(vorlage[name])\r\n", - " vorlage.move_sheet(sheet, 1 - vorlage.index(sheet))\r\n", - " sheet.title = name\r\n", - "\r\n", - " pas = list(abpackDict.values())\r\n", - " pas.sort(key=lambda pa: pa.planPos)\r\n", - " modus = None\r\n", - " time = 0\r\n", - " for pa in pas:\r\n", - " leistung = getPackLeistung(pa.artikelNummer)\r\n", - " if leistung.artikelNummer == \"000000\":\r\n", - " print(f\"Leistungsdaten für Produkt {pa.artikelNummer} nicht verfügbar!\")\r\n", - " \r\n", - " #print(f\"Trying to pack {pa.artikelNummer} with {beutelProH(pa.artikelNummer, pack)}\")\r\n", - " new_modus = leistung.modi[pack]\r\n", - " if time != 0:\r\n", - " if new_modus is None:\r\n", - " print(f\"Leistungsdaten für Produkt {pa.artikelNummer} auf Packerei {pack} nicht verfügbar!\")\r\n", - " time = writePAProdChange(sheet, time, 60, modus, f\"Unbekannt - Leistungsdaten für {pa.artikelNummer} auf {pack} setzen und Leistungsdaten aktualisieren!\")\r\n", - " else:\r\n", - " delta = getWechsel(modus, new_modus, pack)\r\n", - " time = writePAProdChange(sheet, time, delta, modus, new_modus)\r\n", - "\r\n", - " if pa.abpackMenge is None or pa.abpackMenge == 0:\r\n", - " print(f\"Für Produkt {pa.artikelNummer} in Pack {pack} ist keine gültige Abpackmenge eingetragen\")\r\n", - " continue\r\n", - "\r\n", - " time = writePASchedule(sheet, pa, leistung, prodDict, gebGroesse, pack, time)\r\n", - " modus = new_modus\r\n", - " writeEnd(sheet)\r\n", - "\r\n", - "def writeHeader(sheet):\r\n", - " sheet.cell(row=1, column = 1).value = \"ART.NR.\"\r\n", - " sheet.cell(row=1, column = 2).value = \"ART.BEZ.\"\r\n", - " sheet.cell(row=1, column = 3).value = \"GEBINDE\"\r\n", - " sheet.cell(row=1, column = 4).value = \"MENGE\"\r\n", - " sheet.cell(row=1, column = 5).value = \"GEBINDE\"\r\n", - " sheet.cell(row=1, column = 6).value = \"BEUTEL\"\r\n", - " sheet.cell(row=1, column = 7).value = \"PLANPOS\"\r\n", - " sheet.cell(row=1, column = 8).value = \"BEUTEL/H\"\r\n", - " sheet.cell(row=1, column = 9).value = \"DAUER\"\r\n", - " sheet.cell(row=1, column = 10).value = \"ANMERKUNG\"\r\n", - "\r\n", - "def writeEnd(sheet):\r\n", - " row = sheet.max_row + 1\r\n", - " sheet.cell(row=row, column = 9).value = \"30\"\r\n", - " sheet.cell(row=row, column = 10).value = \"Schichtende\"\r\n", - "\r\n", - "def prodTime(nbrBags, performance, min = 30):\r\n", - " return max(int(nbrBags * 60 / performance), 30)\r\n", - "\r\n", - "def writePASchedule(sheet, pa, l, prodDict, gebGroeDict, pack, start):\r\n", - " row = sheet.max_row + 1\r\n", - " geb = gebGroeDict[pa.artikelNummer]\r\n", - " prod = prodDict[pa.artikelNummer]\r\n", - " t = math.ceil(60 * pa.anzBeutel(gebGroeDict) / beutelProH(pa.artikelNummer, pack))\r\n", - " sheet.cell(row=row, column = 1).value = pa.artikelNummer\r\n", - " sheet.cell(row=row, column = 2).value = shortName(pa.artikelNummer)\r\n", - " sheet.cell(row=row, column = 3).value = geb.szBundle\r\n", - " sheet.cell(row=row, column = 4).value = pa.abpackMenge\r\n", - " sheet.cell(row=row, column = 5).value = pa.anzGebinde(gebGroeDict)\r\n", - " sheet.cell(row=row, column = 6).value = pa.anzBeutel(gebGroeDict)\r\n", - " sheet.cell(row=row, column = 7).value = pa.planPos\r\n", - " sheet.cell(row=row, column = 8).value = beutelProH(pa.artikelNummer, pack)\r\n", - " sheet.cell(row=row, column = 9).value = t\r\n", - " sheet.cell(row=row, column = 10).value = pa.bemerkung\r\n", - " sheet.cell(row=row, column = 11).value = pa.bem_ek\r\n", - " sheet.cell(row=row, column = 12).value = pa.roh1\r\n", - " sheet.cell(row=row, column = 13).value = pa.roh1_bes\r\n", - " sheet.cell(row=row, column = 14).value = pa.roh2\r\n", - " sheet.cell(row=row, column = 15).value = pa.roh2_bes\r\n", - "\r\n", - " if l.muehleMisch:\r\n", - " for i in range(1,10):\r\n", - " sheet.cell(row=row, column=i).fill = PatternFill(fgColor=purple, fill_type = 'solid')\r\n", - " if l.muehle:\r\n", - " for i in range(1,10):\r\n", - " sheet.cell(row=row, column=i).fill = PatternFill(fgColor=blue, fill_type = 'solid')\r\n", - "\r\n", - " return start + t\r\n", - "\r\n", - "def writePAProdChange(sheet, start, delta, modFrom, modTo):\r\n", - " row = sheet.max_row + 1\r\n", - " sheet.cell(row=row, column = 9).value = delta\r\n", - " if modFrom != modTo:\r\n", - " sheet.cell(row=row, column = 10).value = f\"Umbau auf {modTo}\"\r\n", - "\r\n", + "# read Dispo\n", + "\n", + "def readDispo(sheet, prodStamm):\n", + " DISPO_DICT = {}\n", + " ABPACK_DICT = {}\n", + " MISCH_DICT = {}\n", + " GEB_GROESSE = {}\n", + " HEADER = True\n", + " for row in sheet.rows:\n", + "\n", + " if HEADER: # skip the header lines\n", + " if row[0].value == \"ARTNR\":\n", + " HEADER = False\n", + " continue\n", + " if row[0].value is None:\n", + " break\n", + "\n", + " product = prodStamm.get(row[0].value, None)\n", + "\n", + " d = DispoBedarf(\n", + " artikelNummer=row[0].value,\n", + " palettenziel=row[4].value,\n", + " bestandL00=row[5].value,\n", + " bestandL01=row[6].value,\n", + " bestandL05=row[7].value,\n", + " auftragsBestand=row[8].value,\n", + " bestellBestand=row[15].value,\n", + " durchschnitt=row[17].value,\n", + " tuetenAnz= 0 if row[24].value is None else int(float(row[24].value)*1000),\n", + " roh1 = row[18].value,\n", + " roh1_bes = row[20].value,\n", + " roh2 = row[21].value,\n", + " roh2_bes = row[22].value,\n", + " bem_ek = row[23].value\n", + " )\n", + "\n", + " g = Bundle.fromString(row[2].value)\n", + "\n", + " DISPO_DICT[d.artikelNummer] = d\n", + " GEB_GROESSE[d.artikelNummer] = g\n", + "\n", + " if not (row[25].value is None):\n", + " a = Abpackung(\n", + " artikelNummer=d.artikelNummer,\n", + " abpackMenge=int(row[25].value),\n", + " bemerkung=\"\",\n", + " planPos= 999 if row[29].value is None else int(int(row[29].value)),\n", + " roh1 = row[18].value,\n", + " roh1_bes = row[20].value,\n", + " roh2 = row[21].value,\n", + " roh2_bes = row[22].value,\n", + " bem_ek = row[23].value\n", + " )\n", + "\n", + " ABPACK_DICT[d.artikelNummer]=a\n", + "\n", + " if not product is None and product.muehleMisch == 1:\n", + " MISCH_DICT[d.artikelNummer] = MischBedarf(\n", + " artikelNummer = d.artikelNummer,\n", + " abpackMenge = int(row[25].value) if not row[25].value is None else 0,\n", + " kw_reich = float(row[16].value),\n", + " bem_ek = row[23].value,\n", + " roh1 = row[18].value,\n", + " roh1_bes = row[20].value,\n", + " roh2 = row[21].value,\n", + " roh2_bes = row[22].value)\n", + "\n", + " return DISPO_DICT, ABPACK_DICT, GEB_GROESSE, MISCH_DICT" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# write Schedule\n", + "def writeMischDispo(vorlage, dP1, dP2, dP3, dP4, prodDict):\n", + " name = f\"MischDispo\"\n", + " sheet = vorlage.copy_worksheet(vorlage[\"MischDispo\"])\n", + " if name in vorlage.sheetnames:\n", + " vorlage.remove(vorlage[name])\n", + " vorlage.move_sheet(sheet, 1 - vorlage.index(sheet))\n", + " sheet.title = name\n", + "\n", + " counter = 0\n", + " for pack, mischDispo in [(\"Pack1\", dP1), (\"Pack2\", dP2), (\"Pack3\", dP3), (\"Pack4\", dP4)]:\n", + " for d in mischDispo.values():\n", + " p = prodDict.get(d.artikelNummer, None)\n", + " if p is None:\n", + " print(f\"ERROR: Product {p.artikelNummer} not found\")\n", + " counter += 1\n", + " sheet.append([pack, d.artikelNummer, p.name, p.bundle, d.kw_reich, d.abpackMenge, d.bem_ek, d.roh1, d.roh1_bes, d.roh2, d.roh2_bes])\n", + "\n", + " tab = Table(displayName=\"MischDispo\", ref=f\"A1:K{counter}\")\n", + " sheet.add_table(tab)\n", + "\n", + "\n", + "def writeSchedule(vorlage, dispo, prodDict, pack):\n", + " name = f\"Schedule {pack}\"\n", + "\n", + " _dispoDict, abpackDict, gebGroesse, _mischDict = dispo\n", + "\n", + " sheet = vorlage.copy_worksheet(vorlage[\"Schedule\"])\n", + " if name in vorlage.sheetnames:\n", + " vorlage.remove(vorlage[name])\n", + " vorlage.move_sheet(sheet, 1 - vorlage.index(sheet))\n", + " sheet.title = name\n", + "\n", + " pas = list(abpackDict.values())\n", + " pas.sort(key=lambda pa: pa.planPos)\n", + " modus = None\n", + " time = 0\n", + " for pa in pas:\n", + " leistung = getPackLeistung(pa.artikelNummer)\n", + " if leistung.artikelNummer == \"000000\":\n", + " print(f\"Leistungsdaten für Produkt {pa.artikelNummer} nicht verfügbar!\")\n", + " \n", + " #print(f\"Trying to pack {pa.artikelNummer} with {beutelProH(pa.artikelNummer, pack)}\")\n", + " new_modus = leistung.modi[pack]\n", + " if time != 0:\n", + " if new_modus is None:\n", + " print(f\"Leistungsdaten für Produkt {pa.artikelNummer} auf Packerei {pack} nicht verfügbar!\")\n", + " time = writePAProdChange(sheet, time, 60, modus, f\"Unbekannt - Leistungsdaten für {pa.artikelNummer} auf {pack} setzen und Leistungsdaten aktualisieren!\")\n", + " else:\n", + " delta = getWechsel(modus, new_modus, pack)\n", + " time = writePAProdChange(sheet, time, delta, modus, new_modus)\n", + "\n", + " if pa.abpackMenge is None or pa.abpackMenge == 0:\n", + " print(f\"Für Produkt {pa.artikelNummer} in Pack {pack} ist keine gültige Abpackmenge eingetragen\")\n", + " continue\n", + "\n", + " time = writePASchedule(sheet, pa, leistung, prodDict, gebGroesse, pack, time)\n", + " modus = new_modus\n", + " writeEnd(sheet)\n", + "\n", + "def writeHeader(sheet):\n", + " sheet.cell(row=1, column = 1).value = \"ART.NR.\"\n", + " sheet.cell(row=1, column = 2).value = \"ART.BEZ.\"\n", + " sheet.cell(row=1, column = 3).value = \"GEBINDE\"\n", + " sheet.cell(row=1, column = 4).value = \"MENGE\"\n", + " sheet.cell(row=1, column = 5).value = \"GEBINDE\"\n", + " sheet.cell(row=1, column = 6).value = \"BEUTEL\"\n", + " sheet.cell(row=1, column = 7).value = \"PLANPOS\"\n", + " sheet.cell(row=1, column = 8).value = \"BEUTEL/H\"\n", + " sheet.cell(row=1, column = 9).value = \"DAUER\"\n", + " sheet.cell(row=1, column = 10).value = \"ANMERKUNG\"\n", + "\n", + "def writeEnd(sheet):\n", + " row = sheet.max_row + 1\n", + " sheet.cell(row=row, column = 9).value = \"30\"\n", + " sheet.cell(row=row, column = 10).value = \"Schichtende\"\n", + "\n", + "def prodTime(nbrBags, performance, min_t = 30):\n", + " return max(int(nbrBags * 60 / performance), min_t)\n", + "\n", + "def writePASchedule(sheet, pa, l, prodDict, gebGroeDict, pack, start):\n", + " row = sheet.max_row + 1\n", + " geb = gebGroeDict[pa.artikelNummer]\n", + " prod = prodDict[pa.artikelNummer]\n", + " # t = math.ceil(60 * pa.anzBeutel(gebGroeDict) / beutelProH(pa.artikelNummer, pack))\n", + " t = prodTime(pa.anzBeutel(gebGroeDict), beutelProH(pa.artikelNummer, pack))\n", + " sheet.cell(row=row, column = 1).value = pa.artikelNummer\n", + " sheet.cell(row=row, column = 2).value = shortName(pa.artikelNummer)\n", + " sheet.cell(row=row, column = 3).value = geb.szBundle\n", + " sheet.cell(row=row, column = 4).value = pa.abpackMenge\n", + " sheet.cell(row=row, column = 5).value = pa.anzGebinde(gebGroeDict)\n", + " sheet.cell(row=row, column = 6).value = pa.anzBeutel(gebGroeDict)\n", + " sheet.cell(row=row, column = 7).value = pa.planPos\n", + " sheet.cell(row=row, column = 8).value = beutelProH(pa.artikelNummer, pack)\n", + " sheet.cell(row=row, column = 9).value = t\n", + " sheet.cell(row=row, column = 10).value = pa.bemerkung\n", + " sheet.cell(row=row, column = 11).value = pa.bem_ek\n", + " sheet.cell(row=row, column = 12).value = pa.roh1\n", + " sheet.cell(row=row, column = 13).value = pa.roh1_bes\n", + " sheet.cell(row=row, column = 14).value = pa.roh2\n", + " sheet.cell(row=row, column = 15).value = pa.roh2_bes\n", + "\n", + "# if l.muehleMisch:\n", + "# for i in range(1,10):\n", + "# sheet.cell(row=row, column=i).fill = PatternFill(fgColor=purple, fill_type = 'solid')\n", + " if l.muehle:\n", + " for i in range(1,10):\n", + " sheet.cell(row=row, column=i).fill = PatternFill(fgColor=blue, fill_type = 'solid')\n", + "\n", + " return start + t\n", + "\n", + "def writePAProdChange(sheet, start, delta, modFrom, modTo):\n", + " row = sheet.max_row + 1\n", + " sheet.cell(row=row, column = 9).value = delta\n", + " if modFrom != modTo:\n", + " sheet.cell(row=row, column = 10).value = f\"Umbau auf {modTo}\"\n", + "\n", " return start + delta" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, - "source": [ - "# Workday\r\n", - "@dataclass\r\n", - "class Workday:\r\n", - " begin: int\r\n", - " end: int\r\n", - " breaks: list\r\n", - "\r\n", - " def to_holliday():\r\n", - " return Workday(0, 0, [])\r\n", - "\r\n", - " def to_1_schicht_WU(begin, end=None):\r\n", - " return Workday(begin, begin + 9 if end is None else end, [3 * 60, 6 * 60])\r\n", - "\r\n", - " def to_1_schicht(begin, end=None):\r\n", - " return Workday(begin, begin + 9.5 if end is None else end, [2.5 * 60, 6 * 60])\r\n", - " \r\n", - " def to_2_schicht(begin, end=None):\r\n", - " return Workday(begin, begin + 18 if end is None else end, [3 * 60, 6.5 * 60, 12 * 60, 15.5 * 60])\r\n", - "\r\n", - " def to_2_schicht_one_only(begin, end=None):\r\n", - " return Workday(begin, begin + 9 if end is None else end, [3 * 60, 6.5 * 60])\r\n", - "\r\n", - " def to_3_schicht(begin, end=None):\r\n", - " return Workday(begin, begin + 24 if end is None else end, [3*60, 9 * 60, 12.5 * 60, 18 * 60, 21.5 * 60])\r\n", - "\r\n", - "@dataclass\r\n", - "class WTemplate:\r\n", - " template: str\r\n", - " packName: str\r\n", - " daySlots: int\r\n", - " dayStart: int\r\n", - " days: tuple\r\n", - "\r\n", - " def to_schicht_wu(begin, packName):\r\n", - " return WTemplate(\r\n", - " \"1-Schicht-WU\",\r\n", - " packName,\r\n", - " 18,\r\n", - " begin,\r\n", - " (\r\n", - " (\"MO\", Workday.to_1_schicht_WU(begin)),\r\n", - " (\"DI\", Workday.to_1_schicht_WU(begin)),\r\n", - " (\"MI\", Workday.to_1_schicht_WU(begin)),\r\n", - " (\"DO\", Workday.to_1_schicht_WU(begin)),\r\n", - " (\"FR\", Workday.to_1_schicht_WU(begin)),\r\n", - " (\"SA\", Workday.to_1_schicht_WU(begin))\r\n", - " ),\r\n", - " )\r\n", - " \r\n", - " def to_schicht_long(begin, packName):\r\n", - " return WTemplate(\r\n", - " \"1-Schicht\",\r\n", - " packName,\r\n", - " 19,\r\n", - " begin,\r\n", - " (\r\n", - " (\"MO\", Workday.to_1_schicht(begin)),\r\n", - " (\"DI\", Workday.to_1_schicht(begin)),\r\n", - " (\"MI\", Workday.to_1_schicht(begin)),\r\n", - " (\"DO\", Workday.to_1_schicht(begin)),\r\n", - " (\"FR\", Workday.to_1_schicht(begin)),\r\n", - " (\"SA\", Workday.to_1_schicht(begin))\r\n", - " ),\r\n", - " )\r\n", - " \r\n", - " def to_schicht_long_mischungen(begin, packName):\r\n", - " return WTemplate(\r\n", - " \"1-Schicht+Mischungen\",\r\n", - " packName,\r\n", - " 19,\r\n", - " begin,\r\n", - " (\r\n", - " (\"MO\", Workday.to_1_schicht(begin)),\r\n", - " (\"DI\", Workday.to_1_schicht(begin)),\r\n", - " (\"MI\", Workday.to_1_schicht(begin)),\r\n", - " (\"DO\", Workday.to_1_schicht(begin)),\r\n", - " (\"FR\", Workday.to_1_schicht(begin)),\r\n", - " (\"SA\", Workday.to_1_schicht(begin))\r\n", - " ),\r\n", - " )\r\n", - "\r\n", - " def to_2_schicht(begin, packName):\r\n", - " return WTemplate(\r\n", - " \"2-Schicht\",\r\n", - " packName,\r\n", - " 36,\r\n", - " begin,\r\n", - " (\r\n", - " (\"MO\", Workday.to_2_schicht(begin)),\r\n", - " (\"DI\", Workday.to_2_schicht(begin)),\r\n", - " (\"MI\", Workday.to_2_schicht(begin)),\r\n", - " (\"DO\", Workday.to_2_schicht(begin)),\r\n", - " (\"FR\", Workday.to_2_schicht(begin)),\r\n", - " (\"SA\", Workday.to_2_schicht(begin)),\r\n", - " )\r\n", - " )\r\n", - " \r\n", - " def to_2_schicht_one_only(begin, packName):\r\n", - " return WTemplate(\r\n", - " \"2-Schicht\",\r\n", - " packName,\r\n", - " 36,\r\n", - " begin,\r\n", - " (\r\n", - " (\"MO\", Workday.to_2_schicht_one_only(begin)),\r\n", - " (\"DI\", Workday.to_2_schicht_one_only(begin)),\r\n", - " (\"MI\", Workday.to_2_schicht_one_only(begin)),\r\n", - " (\"DO\", Workday.to_2_schicht_one_only(begin)),\r\n", - " (\"FR\", Workday.to_2_schicht_one_only(begin)),\r\n", - " (\"SA\", Workday.to_2_schicht_one_only(begin)),\r\n", - " )\r\n", - " )\r\n", - " \r\n", - " def to_2_schicht_special(begin, packName):\r\n", - " return WTemplate(\r\n", - " \"2-Schicht\",\r\n", - " packName,\r\n", - " 36,\r\n", - " begin,\r\n", - " (\r\n", - " (\"MO\", Workday.to_2_schicht(begin)),\r\n", - " (\"DI\", Workday.to_2_schicht(begin)),\r\n", - " (\"MI\", Workday.to_2_schicht_one_only(begin)),\r\n", - " (\"DO\", Workday.to_2_schicht_one_only(begin)),\r\n", - " (\"FR\", Workday.to_2_schicht_one_only(begin)),\r\n", - " (\"SA\", Workday.to_2_schicht_one_only(begin)),\r\n", - " )\r\n", - " )\r\n", - " \r\n", - " def to_3_schicht(begin, packName):\r\n", - " return WTemplate(\r\n", - " \"3-Schicht\",\r\n", - " packName,\r\n", - " 36,\r\n", - " begin,\r\n", - " (\r\n", - " (\"MO\", Workday.to_3_schicht(begin)),\r\n", - " (\"DI\", Workday.to_3_schicht(begin)),\r\n", - " (\"MI\", Workday.to_3_schicht(begin)),\r\n", - " (\"DO\", Workday.to_3_schicht(begin)),\r\n", - " (\"FR\", Workday.to_3_schicht(begin)),\r\n", - " (\"SA\", Workday.to_3_schicht(begin)),\r\n", - " )\r\n", - " )\r\n" - ], + "metadata": {}, "outputs": [], - "metadata": {} + "source": [ + "# Workday\n", + "@dataclass\n", + "class Workday:\n", + " begin: int\n", + " end: int\n", + " breaks: list\n", + "\n", + " def to_holliday():\n", + " return Workday(0, 0, [])\n", + "\n", + " def to_1_schicht_WU(begin, end=None):\n", + " return Workday(begin, begin + 9 if end is None else end, [3 * 60, 6 * 60])\n", + "\n", + " def to_1_schicht(begin, end=None):\n", + " return Workday(begin, begin + 9.5 if end is None else end, [2.5 * 60, 6 * 60])\n", + " \n", + " def to_2_schicht(begin, end=None):\n", + " return Workday(begin, begin + 18 if end is None else end, [3 * 60, 6.5 * 60, 12 * 60, 15.5 * 60])\n", + "\n", + " def to_2_schicht_one_only(begin, end=None):\n", + " return Workday(begin, begin + 9 if end is None else end, [3 * 60, 6.5 * 60])\n", + "\n", + " def to_3_schicht(begin, end=None):\n", + " return Workday(begin, begin + 24 if end is None else end, [3*60, 9 * 60, 12.5 * 60, 18 * 60, 21.5 * 60])\n", + "\n", + "@dataclass\n", + "class WTemplate:\n", + " template: str\n", + " packName: str\n", + " daySlots: int\n", + " dayStart: int\n", + " days: tuple\n", + "\n", + " def to_1_schicht(begin, packName):\n", + " return WTemplate(\n", + " \"1-Schicht-WU\",\n", + " packName,\n", + " 18,\n", + " begin,\n", + " (\n", + " (\"MO\", Workday.to_1_schicht_WU(begin)),\n", + " (\"DI\", Workday.to_1_schicht_WU(begin)),\n", + " (\"MI\", Workday.to_1_schicht_WU(begin)),\n", + " (\"DO\", Workday.to_1_schicht_WU(begin)),\n", + " (\"FR\", Workday.to_1_schicht_WU(begin)),\n", + " (\"SA\", Workday.to_1_schicht_WU(begin))\n", + " ),\n", + " )\n", + "\n", + " def to_1_schicht_holiday(begin, packName):\n", + " return WTemplate(\n", + " \"1-Schicht-WU\",\n", + " packName,\n", + " 18,\n", + " begin,\n", + " (\n", + " (\"MO\", Workday.to_1_schicht_WU(begin)),\n", + " (\"DI\", Workday.to_1_schicht_WU(begin)),\n", + " (\"MI\", Workday.to_1_schicht_WU(begin)),\n", + " (\"DO\", Workday.to_holliday()),\n", + " (\"FR\", Workday.to_1_schicht_WU(begin)),\n", + " (\"SA\", Workday.to_1_schicht_WU(begin))\n", + " ),\n", + " )\n", + " \n", + " def to_schicht_long(begin, packName):\n", + " return WTemplate(\n", + " \"1-Schicht\",\n", + " packName,\n", + " 19,\n", + " begin,\n", + " (\n", + " (\"MO\", Workday.to_1_schicht(begin)),\n", + " (\"DI\", Workday.to_1_schicht(begin)),\n", + " (\"MI\", Workday.to_1_schicht(begin)),\n", + " (\"DO\", Workday.to_1_schicht(begin)),\n", + " (\"FR\", Workday.to_1_schicht(begin)),\n", + " (\"SA\", Workday.to_1_schicht(begin))\n", + " ),\n", + " )\n", + " \n", + " def to_schicht_long_mischungen(begin, packName):\n", + " return WTemplate(\n", + " \"1-Schicht+Mischungen\",\n", + " packName,\n", + " 19,\n", + " begin,\n", + " (\n", + " (\"MO\", Workday.to_1_schicht(begin)),\n", + " (\"DI\", Workday.to_1_schicht(begin)),\n", + " (\"MI\", Workday.to_1_schicht(begin)),\n", + " (\"DO\", Workday.to_1_schicht(begin)),\n", + " (\"FR\", Workday.to_1_schicht(begin)),\n", + " (\"SA\", Workday.to_1_schicht(begin))\n", + " ),\n", + " )\n", + "\n", + " def to_2_schicht(begin, packName):\n", + " return WTemplate(\n", + " \"2-Schicht\",\n", + " packName,\n", + " 36,\n", + " begin,\n", + " (\n", + " (\"MO\", Workday.to_2_schicht(begin)),\n", + " (\"DI\", Workday.to_2_schicht(begin)),\n", + " (\"MI\", Workday.to_2_schicht(begin)),\n", + " (\"DO\", Workday.to_2_schicht(begin)),\n", + " (\"FR\", Workday.to_2_schicht(begin)),\n", + " (\"SA\", Workday.to_2_schicht(begin)),\n", + " )\n", + " )\n", + " \n", + " def to_2_schicht_one_only(begin, packName):\n", + " return WTemplate(\n", + " \"2-Schicht\",\n", + " packName,\n", + " 36,\n", + " begin,\n", + " (\n", + " (\"MO\", Workday.to_2_schicht_one_only(begin)),\n", + " (\"DI\", Workday.to_2_schicht_one_only(begin)),\n", + " (\"MI\", Workday.to_2_schicht_one_only(begin)),\n", + " (\"DO\", Workday.to_2_schicht_one_only(begin)),\n", + " (\"FR\", Workday.to_2_schicht_one_only(begin)),\n", + " (\"SA\", Workday.to_2_schicht_one_only(begin)),\n", + " )\n", + " )\n", + " \n", + " def to_2_schicht_special(begin, packName):\n", + " return WTemplate(\n", + " \"2-Schicht\",\n", + " packName,\n", + " 36,\n", + " begin,\n", + " (\n", + " (\"MO\", Workday.to_2_schicht(begin)),\n", + " (\"DI\", Workday.to_2_schicht(begin)),\n", + " (\"MI\", Workday.to_2_schicht_one_only(begin)),\n", + " (\"DO\", Workday.to_2_schicht_one_only(begin)),\n", + " (\"FR\", Workday.to_2_schicht_one_only(begin)),\n", + " (\"SA\", Workday.to_2_schicht_one_only(begin)),\n", + " )\n", + " )\n", + " \n", + " def to_3_schicht(begin, packName):\n", + " return WTemplate(\n", + " \"3-Schicht\",\n", + " packName,\n", + " 48,\n", + " begin,\n", + " (\n", + " (\"MO\", Workday.to_3_schicht(begin)),\n", + " (\"DI\", Workday.to_3_schicht(begin)),\n", + " (\"MI\", Workday.to_3_schicht(begin)),\n", + " (\"DO\", Workday.to_3_schicht(begin)),\n", + " (\"FR\", Workday.to_3_schicht(begin)),\n", + " (\"SA\", Workday.to_3_schicht(begin)),\n", + " )\n", + " )\n" + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "# Produktdatenbank aufbauen" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, - "source": [ - "ibmconnect = IBMConnector(True)\r\n", - "prodDict = ibmconnect.getProductsTable()\r\n" - ], + "metadata": {}, "outputs": [], - "metadata": {} + "source": [ + "ibmconnect = IBMConnector(True)\n", + "prodDict = ibmconnect.getProductsTable()\n" + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "# Steuerungsdaten" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, - "source": [ - "KW = 39\r\n", - "\r\n", - "# ACHTUNG: Beim Lesen von der Dispo (FROM_DISPO = True) gehen alle bisherigen Planungen verloren!\r\n", - "FROM_DISPO = False # True oder False\r\n", - "\r\n", - "P1 = True\r\n", - "P2 = True\r\n", - "P3 = True\r\n", - "P4 = True\r\n", - "\r\n", - "#DISPO = f\"G:/Allgemein GmbH/Lager und Logistik/Dispo/Dispo Abpackung 2020/Dispo KW {KW-1}.xlsx\"\r\n", - "DISPO = f\"Dispo KW {KW-1}.xlsx\"\r\n", - "PLANUNG_PATH = f\"Wochenplanung KW {KW:02d}_temp.xlsx\"\r\n", - "FINAL_PATH = f\"Wochenplanung KW {KW:02d}.xlsx\"\r\n", - "VORLAGE = \"Abpackplanung Vorlage.xlsx\"\r\n", - "VORDEF = VORLAGE\r\n", - "\r\n", - "WEEK_P1 = WTemplate.to_2_schicht(5, \"Pack1\")\r\n", - "WEEK_P2 = WTemplate.to_2_schicht(5, \"Pack2\")\r\n", - "WEEK_P3 = WTemplate.to_schicht_wu(6, \"Pack3\")\r\n", - "WEEK_P4 = WTemplate.to_schicht_long(7, \"Pack4\")" - ], + "metadata": {}, "outputs": [], - "metadata": {} + "source": [ + "KW = 3\n", + "YEAR = 2022\n", + "\n", + "# ACHTUNG: Beim Lesen von der Dispo (FROM_DISPO = True) gehen alle bisherigen Planungen verloren!\n", + "FROM_DISPO = False # True oder False\n", + "\n", + "P1 = True\n", + "P2 = True\n", + "P3 = True\n", + "P4 = True\n", + "\n", + "#DISPO = f\"G:/Allgemein GmbH/Lager und Logistik/Dispo/Dispo Abpackung 2020/Dispo KW {KW-1}.xlsx\"\n", + "DISPO = f\"Dispo KW {KW-1}.xlsx\"\n", + "PLANUNG_PATH = f\"Wochenplanung KW {KW:02d}_temp.xlsx\"\n", + "FINAL_PATH = f\"Wochenplanung KW {KW:02d}.xlsx\"\n", + "VORLAGE = \"G:/Wochentakt/Packereiplanung/Vorlage/Abpackplanung Vorlage.xlsx\"\n", + "# G:/Allgemein GmbH/Packerei/Abpackplanung 2021/Abpackplanung Vorlage.xlsx\"\n", + "VORDEF = VORLAGE\n", + "\n", + "WEEK_P1 = WTemplate.to_2_schicht(5, \"Pack1\")\n", + "WEEK_P2 = WTemplate.to_2_schicht(5, \"Pack2\")\n", + "WEEK_P3 = WTemplate.to_1_schicht(6, \"Pack3\")\n", + "WEEK_P4 = WTemplate.to_1_schicht(7, \"Pack4\")" + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "# Leistungsdaten lesen" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, - "source": [ - "vorlage = load_workbook(filename = VORLAGE, data_only=True)\r\n", - "\r\n", - "print(\"Read Leistungsdaten\")\r\n", - "sheet = vorlage[\"Leistungsdaten\"]\r\n", - "PACK_VORLAGE = packVorlage(sheet)\r\n", - "LEISTUNGS_DICT = packLeistung(sheet)\r\n", - "\r\n", - "print(\"Read Produktionsstammdaten\")\r\n", - "sheet = vorlage[\"ProduktionStammdaten\"]\r\n", - "PROD_STAMM = produktionStammdaten(sheet)\r\n", - "\r\n", - "vorlage.close()" - ], - "outputs": [], "metadata": { "tags": [] - } + }, + "outputs": [], + "source": [ + "vorlage = load_workbook(filename = VORLAGE, data_only=True)\n", + "\n", + "print(\"Read Leistungsdaten\")\n", + "sheet = vorlage[\"TLeistungsdaten\"]\n", + "PACK_VORLAGE = packVorlage(sheet)\n", + "LEISTUNGS_DICT = packLeistung(sheet)\n", + "\n", + "print(\"Read Produktionsstammdaten\")\n", + "sheet = vorlage[\"ProduktionStammdaten\"]\n", + "PROD_STAMM = produktionStammdaten(sheet)\n", + "\n", + "vorlage.close()" + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "# Dispo lesen & Schedule erstellen" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, - "source": [ - "# read Schedule from Dispo\r\n", - "if FROM_DISPO:\r\n", - " dispo = load_workbook(filename = DISPO, data_only = True, read_only = True)\r\n", - " if P1: dispoP1 = readDispo(dispo[\"Dispo Abpackplanung P1\"])\r\n", - " if P2: dispoP2 = readDispo(dispo[\"Dispo Abpackplanung P2\"])\r\n", - " if P3: dispoP3 = readDispo(dispo[\"Dispo Abpackplanung P3\"])\r\n", - " if P4: dispoP4 = readDispo(dispo[\"Dispo Abpackplanung P4\"])\r\n", - " dispo.close()\r\n", - "\r\n", - " vorlage = load_workbook(filename = VORDEF, data_only = False, read_only = False)\r\n", - " if P4: writeSchedule(vorlage, dispoP4[1], prodDict, dispoP4[2], \"Pack4\")\r\n", - " if P3: writeSchedule(vorlage, dispoP3[1], prodDict, dispoP3[2], \"Pack3\")\r\n", - " if P2: writeSchedule(vorlage, dispoP2[1], prodDict, dispoP2[2], \"Pack2\")\r\n", - " if P1: writeSchedule(vorlage, dispoP1[1], prodDict, dispoP1[2], \"Pack1\")\r\n", - " vorlage.save(PLANUNG_PATH)\r\n", - " vorlage.close() \r\n" - ], - "outputs": [], "metadata": { "tags": [] - } + }, + "outputs": [], + "source": [ + "# read Schedule from Dispo\n", + "if FROM_DISPO:\n", + " dispo = load_workbook(filename = DISPO, data_only = True, read_only = True)\n", + " if P1: dispoP1 = readDispo(dispo[\"Dispo Abpackplanung P1\"], LEISTUNGS_DICT)\n", + " if P2: dispoP2 = readDispo(dispo[\"Dispo Abpackplanung P2\"], LEISTUNGS_DICT)\n", + " if P3: dispoP3 = readDispo(dispo[\"Dispo Abpackplanung P3\"], LEISTUNGS_DICT)\n", + " if P4: dispoP4 = readDispo(dispo[\"Dispo Abpackplanung P4\"], LEISTUNGS_DICT)\n", + " dispo.close()\n", + "\n", + " vorlage = load_workbook(filename = VORDEF, data_only = False, read_only = False)\n", + " writeMischDispo(vorlage, dispoP1[3], dispoP2[3], dispoP3[3], dispoP4[3], prodDict)\n", + " if P4: writeSchedule(vorlage, dispoP4, prodDict, \"Pack4\")\n", + " if P3: writeSchedule(vorlage, dispoP3, prodDict, \"Pack3\")\n", + " if P2: writeSchedule(vorlage, dispoP2, prodDict, \"Pack2\")\n", + " if P1: writeSchedule(vorlage, dispoP1, prodDict, \"Pack1\")\n", + " vorlage.save(PLANUNG_PATH)\n", + " vorlage.close() \n" + ] }, { "cell_type": "code", "execution_count": null, - "source": [ - "# Read update and write Schedule\r\n", - "\r\n", - "def readSchedule(sheet):\r\n", - " pas = []\r\n", - " for idx, row in enumerate(sheet.rows):\r\n", - " if idx == 0:\r\n", - " continue\r\n", - "\r\n", - " # switch between Produktionsauftrag und Umbau / Bemerkung\r\n", - " if row[0].value is None and row[1].value is None:\r\n", - " # Bemerkung / Umbau\r\n", - " pas.append(Bemerkung(\r\n", - " pDauer= int(row[8].value),\r\n", - " bemerkung= row[9].value,\r\n", - " marking = row[0].fill\r\n", - " ))\r\n", - " else: \r\n", - " l = LEISTUNGS_DICT[row[0].value]\r\n", - " pas.append(Produktionsauftrag(\r\n", - " artikelNummer= row[0].value,\r\n", - " artikelBezeichnung= row[1].value,\r\n", - " gebindeGroesse= row[2].value,\r\n", - " abpackMenge= int(row[3].value),\r\n", - " anzGebinde= int(row[4].value),\r\n", - " anzBeutel= int(row[5].value),\r\n", - " pNumber=int(row[6].value),\r\n", - " pLeistung= int(row[7].value),\r\n", - " pDauer= int(row[8].value),\r\n", - " bemerkung= row[9].value,\r\n", - " bem_ek=row[10].value,\r\n", - " roh1=row[11].value,\r\n", - " roh1_bes=row[12].value,\r\n", - " roh2=row[13].value,\r\n", - " roh2_bes=row[14].value,\r\n", - " marking = row[1].fill,\r\n", - " prodDZ = l.duezi,\r\n", - " ))\r\n", - " return pas\r\n", - "\r\n", - "def writePASchedule2(sheet, pa):\r\n", - " row = sheet.max_row + 1\r\n", - " \r\n", - " sheet.cell(row=row, column = 9).value = pa.pDauer\r\n", - " sheet.cell(row=row, column = 10).value = pa.bemerkung\r\n", - "\r\n", - " if isinstance(pa, Produktionsauftrag):\r\n", - " l = getPackLeistung(pa.artikelNummer)\r\n", - " if l.artikelNummer == \"000000\":\r\n", - " print(f\"Leistungsdaten für Produkt {pa.artikelNummer} nicht verfügbar!\")\r\n", - " \r\n", - " sheet.cell(row=row, column = 1).value = pa.artikelNummer\r\n", - " sheet.cell(row=row, column = 2).value = shortName(pa.artikelNummer)\r\n", - " sheet.cell(row=row, column = 3).value = pa.gebindeGroesse\r\n", - " sheet.cell(row=row, column = 4).value = pa.abpackMenge\r\n", - " sheet.cell(row=row, column = 5).value = pa.anzGebinde\r\n", - " sheet.cell(row=row, column = 6).value = pa.anzBeutel\r\n", - " sheet.cell(row=row, column = 7).value = pa.pNumber\r\n", - " sheet.cell(row=row, column = 8).value = pa.pLeistung\r\n", - " sheet.cell(row=row, column = 11).value = pa.bem_ek\r\n", - " sheet.cell(row=row, column = 12).value = pa.roh1\r\n", - " sheet.cell(row=row, column = 13).value = pa.roh1_bes\r\n", - " sheet.cell(row=row, column = 14).value = pa.roh2\r\n", - " sheet.cell(row=row, column = 15).value = pa.roh2_bes\r\n", - " if pa.marking.fgColor.rgb != \"00000000\":\r\n", - " for i in range(1,10):\r\n", - " sheet.cell(row=row, column=i).fill = pa.marking\r\n", - " else:\r\n", - " if l.muehleMisch:\r\n", - " for i in range(1,10):\r\n", - " sheet.cell(row=row, column=i).fill = PatternFill(fgColor=purple, fill_type = 'solid')\r\n", - " if l.muehle:\r\n", - " for i in range(1,10):\r\n", - " sheet.cell(row=row, column=i).fill = PatternFill(fgColor=blue, fill_type = 'solid')\r\n", - "# if l.duezi:\r\n", - "# for i in range(1,10):\r\n", - "# sheet.cell(row=row, column=i).fill = PatternFill(fgColor=orange, fill_type = 'solid')\r\n", - "\r\n", - "\r\n", - "def writeSchedule2(vorlage, pas , pack):\r\n", - " name = f\"Schedule {pack}\"\r\n", - "\r\n", - " sheet = vorlage.copy_worksheet(vorlage[\"Schedule\"])\r\n", - " if name in vorlage.sheetnames:\r\n", - " vorlage.remove(vorlage[name])\r\n", - " vorlage.move_sheet(sheet, -vorlage.index(sheet))\r\n", - " sheet.title = name\r\n", - "\r\n", - " for pa in pas:\r\n", - " #print(f\"Trying to pack {pa.artikelNummer} with {beutelProH(pa.artikelNummer, pack)}\")\r\n", - " if isinstance(pa, Produktionsauftrag):\r\n", - " if pa.abpackMenge is None or pa.abpackMenge == 0:\r\n", - " print(\"This should not happen ...\")\r\n", - " continue\r\n", - "\r\n", - " writePASchedule2(sheet, pa)\r\n", - "\r\n", - "def updateSchedule(sheet, pack):\r\n", - " pas = []\r\n", - " prodDictRev = {prod.name: prod for prod in prodDict.values()}\r\n", - " lastProd = 0\r\n", - "\r\n", - " for idx, row in enumerate(sheet.rows):\r\n", - " if idx == 0:\r\n", - " continue\r\n", - "\r\n", - " # switch between Produktionsauftrag und Umbau / Bemerkung\r\n", - " if row[0].value is None and row[1].value is None:\r\n", - " # Bemerkung / Umbau\r\n", - " pas.append(Bemerkung(\r\n", - " pDauer= int(row[8].value),\r\n", - " bemerkung= row[9].value,\r\n", - " marking = copy(row[0].fill)\r\n", - " ))\r\n", - " else:\r\n", - " assert row[0].value in prodDict or row[1].value in prodDictRev\r\n", - " assert row[3].value\r\n", - " prod = prodDictRev[row[1].value] if row[0].value is None else prodDict[row[0].value]\r\n", - " bundle = Bundle.fromString(prod.bundle)\r\n", - " amount = int(row[3].value)\r\n", - " nbrBags = int(amount * 1000 / bundle.bagWeight) if row[5].value is None else int(row[5].value)\r\n", - " nbrBundles = int(nbrBags / bundle.nbrBags) if row[4].value is None else int(row[4].value)\r\n", - " performance = int(row[7].value)\r\n", - " if performance is None:\r\n", - " l = getPackLeistung(prod.number)\r\n", - " if l.artikelNummer == \"000000\":\r\n", - " print(f\"Leistungsdaten für Produkt {prod.number} nicht verfügbar!\")\r\n", - " \r\n", - " performance = l.leistung.get(pack)\r\n", - " if performance is None:\r\n", - " print(f\"Leistungsdaten für Produkt {prod.number} auf Packerei {pack} nicht verfügbar!\")\r\n", - "\r\n", - " prodNr = lastProd + 1\r\n", - " if not row[6].value is None:\r\n", - " prodNr = int(row[6].value)\r\n", - " lastProdNr = prodNr\r\n", - "\r\n", - " p = prodDict[prod.number]\r\n", - " \r\n", - "\r\n", - " pas.append(Produktionsauftrag(\r\n", - " artikelNummer= prod.number,\r\n", - " artikelBezeichnung= prod.name,\r\n", - " gebindeGroesse= bundle.szBundle,\r\n", - " abpackMenge= amount,\r\n", - " anzGebinde= nbrBundles,\r\n", - " anzBeutel= nbrBags,\r\n", - " pNumber = prodNr,\r\n", - " pLeistung= performance,\r\n", - " pDauer= prodTime(nbrBags, performance) if row[8].value is None else row[8].value,\r\n", - " bemerkung= row[9].value,\r\n", - " bem_ek = row[10].value,\r\n", - " roh1=row[11].value,\r\n", - " roh1_bes=row[12].value,\r\n", - " roh2=row[13].value,\r\n", - " roh2_bes=row[14].value,\r\n", - " marking = copy(row[0].fill),\r\n", - " prodDZ = p.pickArea == \"33\"\r\n", - " ))\r\n", - " return pas" - ], + "metadata": {}, "outputs": [], - "metadata": {} + "source": [ + "# Read update and write Schedule\n", + "\n", + "def readSchedule(sheet):\n", + " pas = []\n", + " for idx, row in enumerate(sheet.rows):\n", + " if idx == 0:\n", + " continue\n", + "\n", + " # switch between Produktionsauftrag und Umbau / Bemerkung\n", + " if row[0].value is None and row[1].value is None:\n", + " # Bemerkung / Umbau\n", + " pas.append(Bemerkung(\n", + " pDauer= int(row[8].value),\n", + " bemerkung= row[9].value,\n", + " marking = row[0].fill\n", + " ))\n", + " else: \n", + " l = LEISTUNGS_DICT[row[0].value]\n", + " pas.append(Produktionsauftrag(\n", + " artikelNummer= row[0].value,\n", + " artikelBezeichnung= row[1].value,\n", + " gebindeGroesse= row[2].value,\n", + " abpackMenge= int(row[3].value),\n", + " anzGebinde= int(row[4].value),\n", + " anzBeutel= int(row[5].value),\n", + " pNumber=int(row[6].value),\n", + " pLeistung= int(row[7].value),\n", + " pDauer= int(row[8].value),\n", + " bemerkung= row[9].value,\n", + " bem_ek=row[10].value,\n", + " roh1=row[11].value,\n", + " roh1_bes=row[12].value,\n", + " roh2=row[13].value,\n", + " roh2_bes=row[14].value,\n", + " marking = row[0].fill,\n", + " prodDZ = l.duezi,\n", + " ))\n", + " return pas\n", + "\n", + "def writePASchedule2(sheet, pa):\n", + " row = sheet.max_row + 1\n", + " \n", + " sheet.cell(row=row, column = 9).value = pa.pDauer\n", + " sheet.cell(row=row, column = 10).value = pa.bemerkung\n", + "\n", + " if isinstance(pa, Produktionsauftrag):\n", + " l = getPackLeistung(pa.artikelNummer)\n", + " if l.artikelNummer == \"000000\":\n", + " print(f\"Leistungsdaten für Produkt {pa.artikelNummer} nicht verfügbar!\")\n", + " \n", + " sheet.cell(row=row, column = 1).value = pa.artikelNummer\n", + " sheet.cell(row=row, column = 2).value = shortName(pa.artikelNummer)\n", + " sheet.cell(row=row, column = 3).value = pa.gebindeGroesse\n", + " sheet.cell(row=row, column = 4).value = pa.abpackMenge\n", + " sheet.cell(row=row, column = 5).value = pa.anzGebinde\n", + " sheet.cell(row=row, column = 6).value = pa.anzBeutel\n", + " sheet.cell(row=row, column = 7).value = pa.pNumber\n", + " sheet.cell(row=row, column = 8).value = pa.pLeistung\n", + " sheet.cell(row=row, column = 11).value = pa.bem_ek\n", + " sheet.cell(row=row, column = 12).value = pa.roh1\n", + " sheet.cell(row=row, column = 13).value = pa.roh1_bes\n", + " sheet.cell(row=row, column = 14).value = pa.roh2\n", + " sheet.cell(row=row, column = 15).value = pa.roh2_bes\n", + " if pa.marking.fgColor.rgb != \"00000000\":\n", + " for i in range(1,10):\n", + " sheet.cell(row=row, column=i).fill = pa.marking\n", + " else:\n", + " if l.muehleMisch:\n", + " for i in range(2,10):\n", + " sheet.cell(row=row, column=i).fill = PatternFill(fgColor=purple, fill_type = 'solid')\n", + " if l.muehle:\n", + " for i in range(1,10):\n", + " sheet.cell(row=row, column=i).fill = PatternFill(fgColor=blue, fill_type = 'solid')\n", + "# if l.duezi:\n", + "# for i in range(1,10):\n", + "# sheet.cell(row=row, column=i).fill = PatternFill(fgColor=orange, fill_type = 'solid')\n", + "\n", + "\n", + "def writeSchedule2(vorlage, pas , pack):\n", + " name = f\"Schedule {pack}\"\n", + "\n", + " sheet = vorlage.copy_worksheet(vorlage[\"Schedule\"])\n", + " if name in vorlage.sheetnames:\n", + " vorlage.remove(vorlage[name])\n", + " vorlage.move_sheet(sheet, -vorlage.index(sheet))\n", + " sheet.title = name\n", + "\n", + " for pa in pas:\n", + " #print(f\"Trying to pack {pa.artikelNummer} with {beutelProH(pa.artikelNummer, pack)}\")\n", + " if isinstance(pa, Produktionsauftrag):\n", + " if pa.abpackMenge is None or pa.abpackMenge == 0:\n", + " print(\"This should not happen ...\")\n", + " continue\n", + "\n", + " writePASchedule2(sheet, pa)\n", + "\n", + "def updateSchedule(sheet, pack):\n", + " pas = []\n", + " lastProd = 0\n", + "\n", + " for idx, row in enumerate(sheet.rows):\n", + " if idx == 0:\n", + " continue\n", + "\n", + " # switch between Produktionsauftrag und Umbau / Bemerkung\n", + " if row[0].value is None and row[1].value is None:\n", + " # Bemerkung / Umbau\n", + " pas.append(Bemerkung(\n", + " pDauer= int(row[8].value),\n", + " bemerkung= row[9].value,\n", + " marking = copy(row[0].fill)\n", + " ))\n", + " else:\n", + " prod = prodDict.get(f\"s{row[0].value}\", None)\n", + " if prod is None:\n", + " print(f\"Could not find product data of {row[0].value}\")\n", + " bundle = Bundle.fromString(prod.bundle)\n", + " amount = int(row[3].value)\n", + " nbrBags = int(amount * 1000 / bundle.bagWeight) if row[5].value is None else int(row[5].value)\n", + " nbrBundles = int(nbrBags / bundle.nbrBags) if row[4].value is None else int(row[4].value)\n", + " performance = int(row[7].value)\n", + " if performance is None:\n", + " l = getPackLeistung(prod.number[1:])\n", + " if l.artikelNummer == \"000000\":\n", + " print(f\"Leistungsdaten für Produkt {prod.number} nicht verfügbar!\")\n", + " \n", + " performance = l.leistung.get(pack)\n", + " if performance is None:\n", + " print(f\"Leistungsdaten für Produkt {prod.number} auf Packerei {pack} nicht verfügbar!\")\n", + "\n", + " prodNr = lastProd + 1\n", + " if not row[6].value is None:\n", + " prodNr = int(row[6].value)\n", + " lastProdNr = prodNr\n", + " \n", + "\n", + " pas.append(Produktionsauftrag(\n", + " artikelNummer= prod.number[1:],\n", + " artikelBezeichnung= prod.name,\n", + " gebindeGroesse= bundle.szBundle,\n", + " abpackMenge= amount,\n", + " anzGebinde= nbrBundles,\n", + " anzBeutel= nbrBags,\n", + " pNumber = prodNr,\n", + " pLeistung= performance,\n", + " pDauer= prodTime(nbrBags, performance) if row[8].value is None else row[8].value,\n", + " bemerkung= row[9].value,\n", + " bem_ek = row[10].value,\n", + " roh1=row[11].value,\n", + " roh1_bes=row[12].value,\n", + " roh2=row[13].value,\n", + " roh2_bes=row[14].value,\n", + " marking = copy(row[0].fill),\n", + " prodDZ = prod.pickArea == \"33\"\n", + " ))\n", + " return pas" + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "# Produktionsplanung schreiben\n", "\n", "nimmt die Schedule und schreibt sie in die Abpackplanungsdatei" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, - "source": [ - "# classes Produktionsauftrag & Bemerkung\r\n", - "@dataclass\r\n", - "class Produktionsauftrag:\r\n", - " artikelNummer: str\r\n", - " artikelBezeichnung: str\r\n", - " gebindeGroesse: str\r\n", - " abpackMenge: int\r\n", - " anzGebinde: int\r\n", - " anzBeutel: int\r\n", - " pNumber: int\r\n", - " pLeistung: int\r\n", - " pDauer: int\r\n", - " bemerkung: str\r\n", - " bem_ek: str\r\n", - " roh1: str # Rohstoff 1\r\n", - " roh1_bes: str # Rohstoff 1 Bestand\r\n", - " roh2: str # Rohstoff 2\r\n", - " roh2_bes: str # Rohstoff 2 Bestand\r\n", - " marking: PatternFill\r\n", - " prodDZ: bool\r\n", - "\r\n", - "@dataclass\r\n", - "class Bemerkung:\r\n", - " pDauer: int\r\n", - " bemerkung: str\r\n", - " marking: PatternFill\r\n", - "\r\n", - " def isSimpleProdChange(self):\r\n", - " return self.bemerkung is None or self.bemerkung == \"\"\r\n" - ], + "metadata": {}, "outputs": [], - "metadata": {} + "source": [ + "# classes Produktionsauftrag & Bemerkung\n", + "@dataclass\n", + "class Produktionsauftrag:\n", + " artikelNummer: str\n", + " artikelBezeichnung: str\n", + " gebindeGroesse: str\n", + " abpackMenge: int\n", + " anzGebinde: int\n", + " anzBeutel: int\n", + " pNumber: int\n", + " pLeistung: int\n", + " pDauer: int\n", + " bemerkung: str\n", + " bem_ek: str\n", + " roh1: str # Rohstoff 1\n", + " roh1_bes: str # Rohstoff 1 Bestand\n", + " roh2: str # Rohstoff 2\n", + " roh2_bes: str # Rohstoff 2 Bestand\n", + " marking: PatternFill\n", + " prodDZ: bool\n", + "\n", + "@dataclass\n", + "class Bemerkung:\n", + " pDauer: int\n", + " bemerkung: str\n", + " marking: PatternFill\n", + "\n", + " def isSimpleProdChange(self):\n", + " return self.bemerkung is None or self.bemerkung == \"\"\n" + ] }, { "cell_type": "code", "execution_count": null, - "source": [ - "# write Schedule to factory plan\r\n", - "\r\n", - "def toTimeString(minutes):\r\n", - " return f\"{int(minutes / 60):2}:{int(minutes % 60):02}\"\r\n", - "\r\n", - "def toTimeSlotString(minutes):\r\n", - " return f\"{toTimeString(minutes)} - {toTimeString(minutes + 30)}\"\r\n", - "\r\n", - "\r\n", - "def fillWorkday(sheet, kw, pack, workday):\r\n", - " # header\r\n", - " sheet.cell(row=2, column=2).value = kw\r\n", - " sheet.cell(row=3, column=1).value = pack\r\n", - "\r\n", - " current = workday.begin * 60\r\n", - " row = 4\r\n", - " while current < workday.end * 60:\r\n", - " sheet.cell(row=row, column=2).value = toTimeSlotString(current)\r\n", - " current += 30\r\n", - " if current >= 24*60:\r\n", - " current = 0\r\n", - " row += 1\r\n", - "\r\n", - "def writeToPlan(sheet, pa, day, startSlot, timeEnd, prodDict, workday):\r\n", - " if isinstance(pa, Produktionsauftrag):\r\n", - " writePA(sheet, pa, day, startSlot, prodDict, workday)\r\n", - " else:\r\n", - " writeComment(sheet, pa, day, startSlot, timeEnd, prodDict, workday)\r\n", - " \r\n", - "\r\n", - "def writeComment(sheet, pa, day, startSlot, timeEnd, prodDict, workday):\r\n", - " assert isinstance(pa, Bemerkung), \"Trying to write PA as Break\"\r\n", - "\r\n", - " if pa.pDauer < 30 or pa.bemerkung is None:\r\n", - " return\r\n", - "\r\n", - " columns = { \"MO\": 3, \"DI\": 13, \"MI\":23, \"DO\":33, \"FR\":43, \"SA\":53 }\r\n", - " columnOffset=columns[day]\r\n", - " rowOffset = 4\r\n", - "\r\n", - " lastSlot = slot(timeEnd)\r\n", - "\r\n", - " sheet.cell(row=rowOffset + startSlot, column=columnOffset+4).value=pa.bemerkung\r\n", - " current = startSlot\r\n", - " while True:\r\n", - " if not slotIsBreak(current, workday):\r\n", - " sheet.cell(row=rowOffset+current, column=columnOffset+4).fill = PatternFill(fgColor=red, fill_type = 'solid')\r\n", - " current += 1\r\n", - " if current >= lastSlot:\r\n", - " break\r\n", - "\r\n", - "def writePA(sheet, pa, day, startSlot, prodDict, workday):\r\n", - " assert isinstance(pa, Produktionsauftrag), \"Trying to write Break as PA\"\r\n", - " \r\n", - " columns = { \"MO\": 3, \"DI\": 13, \"MI\":23, \"DO\":33, \"FR\":43, \"SA\":53 }\r\n", - " columnOffset=columns[day]\r\n", - " rowOffset = 4\r\n", - " \r\n", - " sheet.cell(row=rowOffset+startSlot, column=columnOffset+0).value = pa.anzBeutel\r\n", - " sheet.cell(row=rowOffset+startSlot, column=columnOffset+1).value = pa.anzGebinde\r\n", - " if pa.artikelNummer is None:\r\n", - " sheet.cell(row=rowOffset+startSlot, column=columnOffset+2).value = pa.gebindeGroesse\r\n", - " sheet.cell(row=rowOffset+startSlot, column=columnOffset+4).value = pa.artikelBezeichnung\r\n", - " else:\r\n", - " sheet.cell(row=rowOffset+startSlot, column=columnOffset+3).value = f\"p{pa.artikelNummer}\"\r\n", - " sheet.cell(row=rowOffset+startSlot, column=columnOffset+7).value = pa.abpackMenge\r\n", - " prod = prodDict.get(pa.artikelNummer, None)\r\n", - " sheet.cell(row=rowOffset+startSlot, column=columnOffset+6).value = math.ceil(pa.anzGebinde / prod.palSize) if not prod is None else None\r\n", - " if pa.bemerkung != \"\" and not pa.bemerkung is None and pa.pDauer >= 60:\r\n", - " sheet.cell(row=rowOffset + startSlot + 1, column=columnOffset+4).value=pa.bemerkung\r\n", - " sheet.cell(row=rowOffset + startSlot + 1, column=columnOffset+4).fill = PatternFill(fgColor=yellow, fill_type = 'solid')\r\n", - " if not pa.marking is None:\r\n", - " for i in range(8):\r\n", - " sheet.cell(row=rowOffset+startSlot, column=columnOffset+i).fill = pa.marking\r\n", - " if pa.prodDZ:\r\n", - " sheet.cell(row=rowOffset+startSlot, column=columnOffset+0).fill = PatternFill(fgColor=orange, fill_type = 'solid')\r\n", - " sheet.cell(row=rowOffset+startSlot, column=columnOffset+1).fill = PatternFill(fgColor=orange, fill_type = 'solid')\r\n", - " sheet.cell(row=rowOffset+startSlot, column=columnOffset+2).fill = PatternFill(fgColor=orange, fill_type = 'solid')\r\n", - "\r\n", - "def writeZeitVerschn(sheet, slotsPerDay, day, uebertragZ):\r\n", - " columns = { \"MO\": 3, \"DI\": 13, \"MI\":23, \"DO\":33, \"FR\":43, \"SA\":53 }\r\n", - " columnOffset=columns[day]\r\n", - " rowOffset = 4\r\n", - " sheet.cell(row=rowOffset+slotsPerDay, column=columnOffset+2).value = uebertragZ\r\n", - "\r\n", - " \r\n", - "def writeNegUebertrag(sheet, slotsPerDay, day, uebertrag):\r\n", - " columns = { \"MO\": 3, \"DI\": 13, \"MI\":23, \"DO\":33, \"FR\":43, \"SA\":53 }\r\n", - " columnOffset=columns[day]\r\n", - " rowOffset = 4\r\n", - " sheet.cell(row=rowOffset+slotsPerDay-1, column=columnOffset+0).value = -uebertrag\r\n", - " \r\n", - "def writePosUebertrag(sheet, slotsPerDay, day, uebertrag):\r\n", - " columns = { \"MO\": 3, \"DI\": 13, \"MI\":23, \"DO\":33, \"FR\":43, \"SA\":53 }\r\n", - " columnOffset=columns[day]\r\n", - " rowOffset = 4\r\n", - " sheet.cell(row=rowOffset, column=columnOffset+0).value = uebertrag\r\n", - " sheet.cell(row=rowOffset, column=columnOffset+1).value = \"Rest\"" - ], + "metadata": {}, "outputs": [], - "metadata": {} + "source": [ + "# write Schedule to factory plan\n", + "\n", + "def toTimeString(minutes):\n", + " return f\"{int(minutes / 60):2}:{int(minutes % 60):02}\"\n", + "\n", + "def toTimeSlotString(minutes):\n", + " return f\"{toTimeString(minutes)} - {toTimeString(minutes + 30)}\"\n", + "\n", + "\n", + "def fillWorkday(sheet, kw, year, wtemplate):\n", + " pack = wtemplate.packName\n", + " workday = wtemplate.days[0][1]\n", + " # header\n", + " sheet.cell(row=1, column=1).value = f\"Produktionsplanung {pack}\"\n", + " now = datetime.datetime.now().strftime(\"%d.%m.%Y: %H:%M\")\n", + " sheet.cell(row=wtemplate.daySlots + 14, column=1).value = f\"Stand {now}\"\n", + " sheet.cell(row=2, column=2).value = kw\n", + " sheet.cell(row=3, column=2).value = year\n", + " sheet.cell(row=3, column=1).value = pack\n", + "\n", + " current = workday.begin * 60\n", + " row = 4\n", + " while current < workday.end * 60:\n", + " sheet.cell(row=row, column=2).value = toTimeSlotString(current)\n", + " current += 30\n", + " if current >= 24*60:\n", + " current = 0\n", + " row += 1\n", + "\n", + "def writeToPlan(sheet, pa, day, startSlot, timeEnd, prodDict, workday):\n", + " if isinstance(pa, Produktionsauftrag):\n", + " writePA(sheet, pa, day, startSlot, prodDict, workday)\n", + " else:\n", + " writeComment(sheet, pa, day, startSlot, timeEnd, prodDict, workday)\n", + " \n", + "\n", + "def writeComment(sheet, pa, day, startSlot, timeEnd, prodDict, workday):\n", + " assert isinstance(pa, Bemerkung), \"Trying to write PA as Break\"\n", + "\n", + " if pa.pDauer < 30 or pa.bemerkung is None:\n", + " return\n", + "\n", + " columns = { \"MO\": 3, \"DI\": 13, \"MI\":23, \"DO\":33, \"FR\":43, \"SA\":53 }\n", + " columnOffset=columns[day]\n", + " rowOffset = 4\n", + "\n", + " lastSlot = slot(timeEnd)\n", + "\n", + " sheet.cell(row=rowOffset + startSlot, column=columnOffset+4).value=pa.bemerkung\n", + " current = startSlot\n", + " while True:\n", + " if not slotIsBreak(current, workday):\n", + " sheet.cell(row=rowOffset+current, column=columnOffset+4).fill = PatternFill(fgColor=red, fill_type = 'solid')\n", + " current += 1\n", + " if current >= lastSlot:\n", + " break\n", + "\n", + "def writePA(sheet, pa, day, startSlot, prodDict, workday):\n", + " assert isinstance(pa, Produktionsauftrag), \"Trying to write Break as PA\"\n", + " \n", + " columns = { \"MO\": 3, \"DI\": 13, \"MI\":23, \"DO\":33, \"FR\":43, \"SA\":53 }\n", + " columnOffset=columns[day]\n", + " rowOffset = 4\n", + " \n", + " sheet.cell(row=rowOffset+startSlot, column=columnOffset+0).value = pa.anzBeutel\n", + " sheet.cell(row=rowOffset+startSlot, column=columnOffset+1).value = pa.anzGebinde\n", + " if pa.artikelNummer is None:\n", + " sheet.cell(row=rowOffset+startSlot, column=columnOffset+2).value = pa.gebindeGroesse\n", + " sheet.cell(row=rowOffset+startSlot, column=columnOffset+4).value = pa.artikelBezeichnung\n", + " else:\n", + " sheet.cell(row=rowOffset+startSlot, column=columnOffset+3).value = f\"p{pa.artikelNummer}\"\n", + " sheet.cell(row=rowOffset+startSlot, column=columnOffset+7).value = pa.abpackMenge\n", + " prod = prodDict.get(pa.artikelNummer, None)\n", + " sheet.cell(row=rowOffset+startSlot, column=columnOffset+6).value = math.ceil(pa.anzGebinde / prod.palSize) if not prod is None else None\n", + " if pa.bemerkung != \"\" and not pa.bemerkung is None and pa.pDauer >= 60:\n", + " sheet.cell(row=rowOffset + startSlot + 1, column=columnOffset+4).value=pa.bemerkung\n", + " sheet.cell(row=rowOffset + startSlot + 1, column=columnOffset+4).fill = PatternFill(fgColor=yellow, fill_type = 'solid')\n", + " if not pa.marking is None:\n", + " for i in range(8):\n", + " sheet.cell(row=rowOffset+startSlot, column=columnOffset+i).fill = pa.marking\n", + " if pa.prodDZ:\n", + " sheet.cell(row=rowOffset+startSlot, column=columnOffset+0).fill = PatternFill(fgColor=orange, fill_type = 'solid')\n", + " sheet.cell(row=rowOffset+startSlot, column=columnOffset+1).fill = PatternFill(fgColor=orange, fill_type = 'solid')\n", + " sheet.cell(row=rowOffset+startSlot, column=columnOffset+2).fill = PatternFill(fgColor=orange, fill_type = 'solid')\n", + "\n", + "def writeZeitVerschn(sheet, slotsPerDay, day, uebertragZ):\n", + " columns = { \"MO\": 3, \"DI\": 13, \"MI\":23, \"DO\":33, \"FR\":43, \"SA\":53 }\n", + " columnOffset=columns[day]\n", + " rowOffset = 4\n", + " sheet.cell(row=rowOffset+slotsPerDay, column=columnOffset+2).value = uebertragZ\n", + "\n", + " \n", + "def writeNegUebertrag(sheet, slotsPerDay, day, uebertrag):\n", + " columns = { \"MO\": 3, \"DI\": 13, \"MI\":23, \"DO\":33, \"FR\":43, \"SA\":53 }\n", + " columnOffset=columns[day]\n", + " rowOffset = 4\n", + " sheet.cell(row=rowOffset+slotsPerDay-1, column=columnOffset+0).value = -uebertrag\n", + " \n", + "def writePosUebertrag(sheet, slotsPerDay, day, uebertrag):\n", + " columns = { \"MO\": 3, \"DI\": 13, \"MI\":23, \"DO\":33, \"FR\":43, \"SA\":53 }\n", + " columnOffset=columns[day]\n", + " rowOffset = 4\n", + " sheet.cell(row=rowOffset, column=columnOffset+0).value = uebertrag\n", + " sheet.cell(row=rowOffset, column=columnOffset+1).value = \"Rest\"\n", + " sheet.cell(row=rowOffset, column=columnOffset+6).value = \"\"" + ] }, { "cell_type": "code", "execution_count": null, - "source": [ - "# write Schedule to factory plan 2\r\n", - "def slot(time):\r\n", - " return max(0, math.floor(time / 30))\r\n", - "\r\n", - "def slotIsBreak(s, workday):\r\n", - " breakSlots = set(map(lambda b: slot(b), workday.breaks))\r\n", - "\r\n", - " return s in breakSlots\r\n", - "\r\n", - "def timeAdd(current, add, breaks):\r\n", - " newTime = current + add\r\n", - " # find the next break\r\n", - " nextBreak = 0\r\n", - " while nextBreak < len(breaks):\r\n", - " if breaks[nextBreak] > current:\r\n", - " break\r\n", - " nextBreak += 1\r\n", - "\r\n", - " # next break settled\r\n", - " for b in breaks[nextBreak:-1]:\r\n", - " if b <= newTime:\r\n", - " newTime += 30\r\n", - "\r\n", - " return (newTime, breaks[-1] - newTime)\r\n", - "\r\n", - "\r\n", - "def writeAbpackplan(vorlage, wtemplate, schedule, prodDict):\r\n", - " days = wtemplate.days\r\n", - " sheet = vorlage.copy_worksheet(vorlage[wtemplate.template])\r\n", - " if wtemplate.packName in vorlage.sheetnames:\r\n", - " vorlage.remove(vorlage[wtemplate.packName])\r\n", - " vorlage.move_sheet(sheet, -vorlage.index(sheet))\r\n", - " sheet.title = wtemplate.packName\r\n", - "\r\n", - "\r\n", - " time = 0\r\n", - " paIdx = 0\r\n", - " remainingT = 0\r\n", - " uebertrag = None\r\n", - " fillWorkday(sheet, KW, wtemplate.packName, days[0][1])\r\n", - " \r\n", - " for day, schicht in wtemplate.days:\r\n", - " if schicht.begin == schicht.end:\r\n", - " # holliday\r\n", - " continue\r\n", - " \r\n", - " dayLength = (schicht.end - schicht.begin) * 60\r\n", - " breaks = schicht.breaks + [(schicht.end - schicht.begin) * 60,]\r\n", - " slotsPerDay = wtemplate.daySlots\r\n", - " time, remainingT = timeAdd(schicht.begin - wtemplate.dayStart, remainingT, breaks)\r\n", - " currentSlot = slot(time)\r\n", - " if not uebertrag is None:\r\n", - " writePosUebertrag(sheet, slotsPerDay, day, uebertrag)\r\n", - " uebertrag = None\r\n", - " \r\n", - " if remainingT < 0: # running into the next day\r\n", - " uebertragVerhältnis = -remainingT / currentPA.pDauer\r\n", - " uebertragMenge = int(uebertragVerhältnis * currentPA.anzBeutel)\r\n", - "\r\n", - " writeNegUebertrag(sheet, slotsPerDay + 1, day, uebertragMenge)\r\n", - " uebertrag = uebertragMenge\r\n", - "\r\n", - " remainingT = -remainingT\r\n", - " continue\r\n", - "\r\n", - " remainingT = max(30, remainingT)\r\n", - " \r\n", - "\r\n", - " while paIdx < len(schedule):\r\n", - " currentPA = schedule[paIdx] \r\n", - " if remainingT <= 15 and currentPA.pDauer > 30:\r\n", - " time = 0\r\n", - " break\r\n", - "\r\n", - " currentSlot = slot(time)\r\n", - " newtime, remainingT = timeAdd(time, currentPA.pDauer, breaks)\r\n", - "\r\n", - " writeToPlan(sheet, currentPA, day, currentSlot, newtime, prodDict, schicht)\r\n", - " lastSlot = currentSlot\r\n", - " \r\n", - " if remainingT < 0: # running into the next day\r\n", - " if remainingT < -15:\r\n", - " if type(currentPA) == Produktionsauftrag:\r\n", - " uebertragVerhältnis = -remainingT / currentPA.pDauer\r\n", - " uebertragMenge = int(uebertragVerhältnis * currentPA.anzBeutel)\r\n", - "\r\n", - " writeNegUebertrag(sheet, slotsPerDay + 1, day, uebertragMenge)\r\n", - " uebertrag = uebertragMenge\r\n", - " remainingT = -remainingT\r\n", - " else:\r\n", - " uebertrag = None\r\n", - " remainingT = 0\r\n", - "\r\n", - " paIdx += 1\r\n", - " break\r\n", - "\r\n", - " paIdx += 1\r\n", - " time = newtime\r\n", - "\r\n", - " if paIdx < len(schedule):\r\n", - " print(f\"Week is full!\")\r\n" - ], - "outputs": [], "metadata": { "tags": [] - } + }, + "outputs": [], + "source": [ + "# write Schedule to factory plan 2\n", + "def slot(time):\n", + " return max(0, math.floor(time / 30))\n", + "\n", + "def slotIsBreak(s, workday):\n", + " breakSlots = set(map(lambda b: slot(b), workday.breaks))\n", + "\n", + " return s in breakSlots\n", + "\n", + "def timeAdd(current, add, breaks):\n", + " newTime = current + add\n", + " # find the next break\n", + " nextBreak = 0\n", + " while nextBreak < len(breaks):\n", + " if breaks[nextBreak] > current:\n", + " break\n", + " nextBreak += 1\n", + "\n", + " # next break settled\n", + " for b in breaks[nextBreak:-1]:\n", + " if b <= newTime:\n", + " newTime += 30\n", + "\n", + " return (newTime, breaks[-1] - newTime)\n", + "\n", + "\n", + "def writeAbpackplan(vorlage, wtemplate, schedule, prodDict, p2=False):\n", + " days = wtemplate.days\n", + " sheet = vorlage.copy_worksheet(vorlage[wtemplate.template])\n", + " if wtemplate.packName in vorlage.sheetnames:\n", + " vorlage.remove(vorlage[wtemplate.packName])\n", + " vorlage.move_sheet(sheet, -vorlage.index(sheet))\n", + " sheet.title = wtemplate.packName\n", + "\n", + "\n", + " time = 15\n", + " paIdx = 0\n", + " remainingT = 0\n", + " uebertrag = None\n", + " fillWorkday(sheet, KW, YEAR, wtemplate)\n", + " \n", + " for day, schicht in wtemplate.days:\n", + " if schicht.begin == schicht.end:\n", + " # holliday\n", + " continue\n", + " \n", + " dayLength = (schicht.end - schicht.begin) * 60\n", + " breaks = schicht.breaks + [(schicht.end - schicht.begin) * 60,]\n", + " slotsPerDay = wtemplate.daySlots\n", + " time, remainingT = timeAdd(schicht.begin - wtemplate.dayStart, remainingT, breaks)\n", + " currentSlot = slot(time)\n", + " if not uebertrag is None:\n", + " writePosUebertrag(sheet, slotsPerDay, day, uebertrag)\n", + " uebertrag = None\n", + " \n", + " if remainingT < 0: # running into the next day\n", + " uebertragVerhältnis = -remainingT / currentPA.pDauer\n", + " uebertragMenge = int(uebertragVerhältnis * currentPA.anzBeutel)\n", + "\n", + " writeNegUebertrag(sheet, slotsPerDay + 1, day, uebertragMenge)\n", + " uebertrag = uebertragMenge\n", + "\n", + " remainingT = -remainingT\n", + " continue\n", + "\n", + " remainingT = 15 + max(15, remainingT )\n", + " \n", + "\n", + " while paIdx < len(schedule):\n", + " currentPA = schedule[paIdx] \n", + " if remainingT <= 15 and currentPA.pDauer > 30:\n", + " time = 15\n", + " break\n", + "\n", + " currentSlot = slot(time)\n", + " newtime, remainingT = timeAdd(time, currentPA.pDauer, breaks)\n", + "\n", + " writeToPlan(sheet, currentPA, day, currentSlot, newtime, prodDict, schicht)\n", + " lastSlot = currentSlot\n", + " \n", + " if remainingT < 0: # running into the next day\n", + " if remainingT < -15:\n", + " if type(currentPA) == Produktionsauftrag:\n", + " uebertragVerhältnis = -remainingT / currentPA.pDauer\n", + " uebertragMenge = int(uebertragVerhältnis * currentPA.anzBeutel)\n", + "\n", + " writeNegUebertrag(sheet, slotsPerDay + 1, day, uebertragMenge)\n", + " uebertrag = uebertragMenge\n", + " remainingT = -remainingT\n", + " else:\n", + " uebertrag = None\n", + " remainingT = 0\n", + "\n", + " paIdx += 1\n", + " break\n", + "\n", + " paIdx += 1\n", + " time = newtime\n", + "\n", + " if paIdx < len(schedule):\n", + " print(f\"Week is full!\")\n" + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "# Update Schedule" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, - "source": [ - "vorlage = load_workbook(filename = PLANUNG_PATH, data_only = False, read_only = False)\r\n", - "try:\r\n", - " if P4:\r\n", - " print(\"Updating P4 ...\")\r\n", - " scheduleP4 = updateSchedule(vorlage[\"Schedule Pack4\"], \"Pack4\")\r\n", - " writeSchedule2(vorlage, scheduleP4, \"Pack4\")\r\n", - " writeAbpackplan(vorlage, WEEK_P4, scheduleP4, prodDict)\r\n", - " if P3:\r\n", - " print(\"Updating P3 ...\")\r\n", - " scheduleP3 = updateSchedule(vorlage[\"Schedule Pack3\"], \"Pack3\")\r\n", - " writeSchedule2(vorlage, scheduleP3, \"Pack3\")\r\n", - " writeAbpackplan(vorlage, WEEK_P3, scheduleP3, prodDict)\r\n", - " if P2: \r\n", - " print(\"Updating P2 ...\")\r\n", - " scheduleP2 = updateSchedule(vorlage[\"Schedule Pack2\"], \"Pack1\")\r\n", - " writeSchedule2(vorlage, scheduleP2, \"Pack2\")\r\n", - " writeAbpackplan(vorlage, WEEK_P2, scheduleP2, prodDict)\r\n", - " if P1:\r\n", - " print(\"Updating P1 ...\")\r\n", - " scheduleP1 = updateSchedule(vorlage[\"Schedule Pack1\"], \"Pack1\")\r\n", - " writeSchedule2(vorlage, scheduleP1, \"Pack1\")\r\n", - " writeAbpackplan(vorlage, WEEK_P1, scheduleP1, prodDict)\r\n", - "\r\n", - " sheet = vorlage[\"Mischungen\"]\r\n", - " sheet[\"B2\"] = KW\r\n", - " \r\n", - " print(\"\\nWriting to file ...\")\r\n", - " vorlage.save(PLANUNG_PATH)\r\n", - " print(\"done!\")\r\n", - "except PermissionError:\r\n", - " print(f\"Saving the Excel file failed. Is it still open?\")\r\n", - "finally:\r\n", - " vorlage.close()" - ], - "outputs": [], "metadata": { "tags": [] - } + }, + "outputs": [], + "source": [ + "vorlage = load_workbook(filename = PLANUNG_PATH, data_only = False, read_only = False)\n", + "try:\n", + " if P4:\n", + " print(\"Updating P4 ...\")\n", + " scheduleP4 = updateSchedule(vorlage[\"Schedule Pack4\"], \"Pack4\")\n", + " writeSchedule2(vorlage, scheduleP4, \"Pack4\")\n", + " writeAbpackplan(vorlage, WEEK_P4, scheduleP4, prodDict)\n", + " if P3:\n", + " print(\"Updating P3 ...\")\n", + " scheduleP3 = updateSchedule(vorlage[\"Schedule Pack3\"], \"Pack3\")\n", + " writeSchedule2(vorlage, scheduleP3, \"Pack3\")\n", + " writeAbpackplan(vorlage, WEEK_P3, scheduleP3, prodDict)\n", + " if P2: \n", + " print(\"Updating P2 ...\")\n", + " scheduleP2 = updateSchedule(vorlage[\"Schedule Pack2\"], \"Pack1\")\n", + " writeSchedule2(vorlage, scheduleP2, \"Pack2\")\n", + " writeAbpackplan(vorlage, WEEK_P2, scheduleP2, prodDict)\n", + " if P1:\n", + " print(\"Updating P1 ...\")\n", + " scheduleP1 = updateSchedule(vorlage[\"Schedule Pack1\"], \"Pack1\")\n", + " writeSchedule2(vorlage, scheduleP1, \"Pack1\")\n", + " writeAbpackplan(vorlage, WEEK_P1, scheduleP1, prodDict)\n", + "\n", + " sheet = vorlage[\"Mischungen\"]\n", + " sheet[\"B2\"] = KW\n", + " \n", + " print(\"\\nWriting to file ...\")\n", + " vorlage.save(PLANUNG_PATH)\n", + " print(\"done!\")\n", + "except PermissionError:\n", + " print(f\"Saving the Excel file failed. Is it still open?\")\n", + "finally:\n", + " vorlage.close()" + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "# Produktionsplanung finalisieren" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, - "source": [ - "def finalizeSheet(sheet):\r\n", - " for row in sheet.iter_rows():\r\n", - " for cell in row:\r\n", - " if cell.value == \"#N/A\":\r\n", - " cell.value = None \r\n", - "\r\n", - "def finalize(vorlage):\r\n", - " for pack in [\"Pack4\", \"Pack3\", \"Pack2\", \"Pack1\"]:\r\n", - " sheet = vorlage[pack]\r\n", - " vorlage.move_sheet(sheet, -vorlage.index(sheet))\r\n", - " finalizeSheet(vorlage[pack])\r\n", - " \r\n", - " sheet = vorlage[\"Mischungen\"]\r\n", - " sheet[\"B2\"] = KW\r\n", - " vorlage.move_sheet(sheet, -vorlage.index(sheet) + 4)\r\n", - " \r\n", - " removeUnused(vorlage)\r\n", - " \r\n", - "def removeUnused(vorlage):\r\n", - " vorlage.remove(vorlage[\"Schedule\"])\r\n", - " vorlage.remove(vorlage[\"1-Schicht\"])\r\n", - " vorlage.remove(vorlage[\"1-Schicht-WU\"])\r\n", - " vorlage.remove(vorlage[\"1-Schicht+Mischungen\"])\r\n", - " vorlage.remove(vorlage[\"2-Schicht\"])\r\n", - " vorlage.remove(vorlage[\"3-Schicht\"])\r\n", - " vorlage.remove(vorlage[\"ProduktionStammdaten\"])\r\n", - " vorlage.remove(vorlage[\"Leistungsdaten\"])\r\n", - " vorlage.remove(vorlage[\"Artikelstamm\"])\r\n", - "\r\n", - "try:\r\n", - " weekPlan = load_workbook(filename = PLANUNG_PATH, data_only = True, read_only = False)\r\n", - " finalize(weekPlan)\r\n", - " weekPlan.save(FINAL_PATH)\r\n", - "except:\r\n", - " print(f\"Saving the Excel file {PLANUNG_PATH} failed. Is it still opened?\")\r\n", - "finally:\r\n", - " weekPlan.close()" - ], + "metadata": {}, "outputs": [], - "metadata": {} + "source": [ + "def finalizeSheet(sheet):\n", + " for row in sheet.iter_rows():\n", + " for cell in row:\n", + " if cell.value == \"#N/A\":\n", + " cell.value = None \n", + "\n", + "def finalize(vorlage):\n", + " for pack in [\"Mischungen\", \"Pack4\", \"Pack3\", \"Pack2\", \"Pack1\"]:\n", + " #for pack in [\"Pack3\", \"Pack2\", \"Pack1\"]:\n", + " sheet = vorlage[pack]\n", + " vorlage.move_sheet(sheet, -vorlage.index(sheet))\n", + " finalizeSheet(vorlage[pack])\n", + " \n", + " sheet = vorlage[\"Mischungen\"]\n", + " sheet[\"B2\"] = KW\n", + " vorlage.move_sheet(sheet, -vorlage.index(sheet) + 4)\n", + " \n", + " removeUnused(vorlage)\n", + " \n", + "def removeUnused(vorlage):\n", + " vorlage.remove(vorlage[\"Schedule\"])\n", + " vorlage.remove(vorlage[\"1-Schicht\"])\n", + " vorlage.remove(vorlage[\"1-Schicht-WU\"])\n", + " vorlage.remove(vorlage[\"1-Schicht+Mischungen\"])\n", + " vorlage.remove(vorlage[\"2-Schicht\"])\n", + " vorlage.remove(vorlage[\"3-Schicht\"])\n", + " vorlage.remove(vorlage[\"ProduktionStammdaten\"])\n", + " vorlage.remove(vorlage[\"TLeistungsdaten\"])\n", + " vorlage.remove(vorlage[\"Artikelstamm\"])\n", + "\n", + "try:\n", + " weekPlan = load_workbook(filename = PLANUNG_PATH, data_only = True, read_only = False)\n", + " \n", + " finalize(weekPlan)\n", + " weekPlan.save(FINAL_PATH)\n", + "except :\n", + " print(f\"Saving the Excel file {FINAL_PATH} failed. Is it still opened?\")\n", + "finally:\n", + " weekPlan.close()" + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "# Create List of WG Brackenheim products" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, - "source": [ - "from openpyxl.styles import Border, Side\r\n", - "thin = Side(border_style=\"thin\", color=\"000000\")\r\n", - "\r\n", - "productset = [p for p in scheduleP1 if isinstance(p, Produktionsauftrag)]\r\n", - "productset.extend([p for p in scheduleP2 if isinstance(p, Produktionsauftrag)])\r\n", - "productset.extend([p for p in scheduleP4 if isinstance(p, Produktionsauftrag)])\r\n", - "\r\n", - "FINAL = f\"WG Brackenheim KW{KW}.xlsx\"\r\n", - "VORLAGE = f\"Dürrenzimmernvorlage.xlsx\"\r\n", - "vorlage = load_workbook(VORLAGE, data_only=False, read_only = False)\r\n", - "sheet = vorlage.active\r\n", - "try:\r\n", - " row = 3\r\n", - " for pa in productset:\r\n", - " prod = prodDict[pa.artikelNummer]\r\n", - " if prod.pickArea != \"33\":\r\n", - " continue\r\n", - " sheet.cell(row = row, column = 1).value = pa.artikelNummer\r\n", - " sheet.cell(row = row, column = 1).border = Border(bottom=thin, top=thin)\r\n", - " sheet.cell(row = row, column = 2).value = pa.artikelBezeichnung\r\n", - " sheet.cell(row = row, column = 2).border = Border(bottom=thin, top=thin)\r\n", - " sheet.cell(row = row, column = 3).value = prod.bundle\r\n", - " sheet.cell(row = row, column = 3).border = Border(bottom=thin, top=thin)\r\n", - " sheet.cell(row = row, column = 4).value = math.ceil(pa.anzGebinde / (prod.palSize * 2 if prod.palSize == 64 else prod.palSize))\r\n", - " sheet.cell(row = row, column = 4).border = Border(bottom=thin, top=thin)\r\n", - " row += 1\r\n", - " vorlage.save(FINAL)\r\n", - "finally:\r\n", - " vorlage.close()" - ], + "metadata": {}, "outputs": [], - "metadata": {} + "source": [ + "from openpyxl.styles import Border, Side\n", + "thin = Side(border_style=\"thin\", color=\"000000\")\n", + "\n", + "productset = [p for p in scheduleP1 if isinstance(p, Produktionsauftrag)]\n", + "productset.extend([p for p in scheduleP2 if isinstance(p, Produktionsauftrag)])\n", + "productset.extend([p for p in scheduleP4 if isinstance(p, Produktionsauftrag)])\n", + "\n", + "FINAL = f\"WG Brackenheim KW{KW}.xlsx\"\n", + "VORLAGE = f\"Dürrenzimmernvorlage.xlsx\"\n", + "vorlage = load_workbook(VORLAGE, data_only=False, read_only = False)\n", + "sheet = vorlage.active\n", + "try:\n", + " row = 3\n", + " for pa in productset:\n", + " prod = prodDict[pa.artikelNummer]\n", + " if prod.pickArea != \"33\":\n", + " continue\n", + " sheet.cell(row = row, column = 1).value = pa.artikelNummer\n", + " sheet.cell(row = row, column = 1).border = Border(bottom=thin, top=thin)\n", + " sheet.cell(row = row, column = 2).value = pa.artikelBezeichnung\n", + " sheet.cell(row = row, column = 2).border = Border(bottom=thin, top=thin)\n", + " sheet.cell(row = row, column = 3).value = prod.bundle\n", + " sheet.cell(row = row, column = 3).border = Border(bottom=thin, top=thin)\n", + " sheet.cell(row = row, column = 4).value = math.ceil(pa.anzGebinde / (prod.palSize * 2 if prod.palSize == 64 else prod.palSize))\n", + " sheet.cell(row = row, column = 4).border = Border(bottom=thin, top=thin)\n", + " row += 1\n", + " vorlage.save(FINAL)\n", + "finally:\n", + " vorlage.close()" + ] }, { "cell_type": "markdown", + "metadata": {}, "source": [ "# Create a checklist for bags" - ], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, - "source": [ - "PLANUNG_PATH_OLD = f\"Wochenplanung KW {KW-1:02d}_temp.xlsx\"\r\n", - "scheduleOld = load_workbook(filename = PLANUNG_PATH_OLD, data_only = False, read_only = False)\r\n", - "try:\r\n", - " scheduleP4Old = readSchedule(schedule[\"Schedule Pack4\"])\r\n", - " scheduleP2Old = readSchedule(schedule[\"Schedule Pack2\"])\r\n", - " scheduleP1Old = readSchedule(schedule[\"Schedule Pack1\"])\r\n", - "except PermissionError:\r\n", - " print(f\"Reading the Excel file {PLANUNG_PATH_OLD} failed. Is it still open?\")\r\n", - "finally:\r\n", - " schedule.close()\r\n" - ], + "metadata": {}, "outputs": [], - "metadata": {} + "source": [ + "PLANUNG_PATH_OLD = f\"Wochenplanung KW {KW-1:02d}_temp.xlsx\"\n", + "scheduleOld = load_workbook(filename = PLANUNG_PATH_OLD, data_only = False, read_only = False)\n", + "try:\n", + " scheduleP4Old = readSchedule(scheduleOld[\"Schedule Pack4\"])\n", + " scheduleP2Old = readSchedule(scheduleOld[\"Schedule Pack2\"])\n", + " scheduleP1Old = readSchedule(scheduleOld[\"Schedule Pack1\"])\n", + "except PermissionError:\n", + " print(f\"Reading the Excel file {PLANUNG_PATH_OLD} failed. Is it still open?\")\n", + "finally:\n", + " scheduleOld.close()\n" + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ - "productset = [p.artikelNummer for p in scheduleP1Old if isinstance(p, Produktionsauftrag)]\r\n", - "productset.extend([p.artikelNummer for p in scheduleP2Old if isinstance(p, Produktionsauftrag)])\r\n", - "productset.extend([p.artikelNummer for p in scheduleP4Old if isinstance(p, Produktionsauftrag)])\r\n", - "\r\n", - "HLB_COUNT_PATH = f\"Zaehlliste KW{KW-1}.xlsx\"\r\n", - "HLB_VORLAGE_PATH = \"Abruf HLB Vorlage - Lagerplätze.xlsx\"\r\n", - "vorlage_hlb = load_workbook(HLB_VORLAGE_PATH, data_only=True, read_only = False)\r\n", - "sheet = vorlage_hlb[\"Tüten HLB\"]\r\n", - "header = [\"Artikelnr. Tüten\", \"Format\", \"Artikelnr. VP\", \"Bezeichnung\", \"Tütengröße\", \"Menge pro Karton\", \"\", \"Marke\", \"Lagerplatz Reihe\", \"Lagerplatz Position\", \"Bemerkungen\", \"Kartons\", \"Stück\", \"Bestellung Karton\", \"In Stück\"]\r\n", - "to_count = set()\r\n", - "try:\r\n", - " for row in sheet.iter_rows(min_row=2, max_row=len(sheet['A']), max_col=15, values_only=True):\r\n", - " artNr = row[2]\r\n", - " if artNr in productset:\r\n", - " to_count.add(row)\r\n", - "finally:\r\n", + "productset = [p.artikelNummer for p in scheduleP1Old if isinstance(p, Produktionsauftrag)]\n", + "productset.extend([p.artikelNummer for p in scheduleP2Old if isinstance(p, Produktionsauftrag)])\n", + "productset.extend([p.artikelNummer for p in scheduleP4Old if isinstance(p, Produktionsauftrag)])\n", + "\n", + "HLB_COUNT_PATH = f\"Zaehlliste KW{KW-1}.xlsx\"\n", + "HLB_VORLAGE_PATH = \"Abruf HLB Vorlage - Lagerplätze.xlsx\"\n", + "vorlage_hlb = load_workbook(HLB_VORLAGE_PATH, data_only=True, read_only = False)\n", + "sheet = vorlage_hlb[\"Tüten HLB\"]\n", + "header = [\"Artikelnr. Tüten\", \"Format\", \"Artikelnr. VP\", \"Bezeichnung\", \"Tütengröße\", \"Menge pro Karton\", \"\", \"Marke\", \"Lagerplatz Reihe\", \"Lagerplatz Position\", \"Bemerkungen\", \"Kartons\", \"Stück\", \"Bestellung Karton\", \"In Stück\"]\n", + "to_count = set()\n", + "try:\n", + " for row in sheet.iter_rows(min_row=2, max_row=len(sheet['A']), max_col=15, values_only=True):\n", + " artNr = row[2]\n", + " if artNr in productset:\n", + " to_count.add(row)\n", + "finally:\n", " vorlage_hlb.close()" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ - "hlb_count = Workbook()\r\n", - "sheet = hlb_count.active\r\n", - "sheet.title = \"HLB Tüten\"\r\n", - "try:\r\n", - " sheet.append((header))\r\n", - " to_count_list = list()\r\n", - " to_count_list.extend(to_count)\r\n", - " to_count_list.sort(key = lambda i: i[2])\r\n", - " for row in to_count_list:\r\n", - " sheet.append(row)\r\n", - " \r\n", - " tab = Table(displayName=\"Counting\", ref=f\"A1:O{len(to_count_list)+2}\")\r\n", - "\r\n", - " sheet.add_table(tab)\r\n", - " hlb_count.save(HLB_COUNT_PATH)\r\n", - "finally:\r\n", + "hlb_count = Workbook()\n", + "sheet = hlb_count.active\n", + "sheet.title = \"HLB Tüten\"\n", + "try:\n", + " sheet.append((header))\n", + " to_count_list = list()\n", + " to_count_list.extend(to_count)\n", + " to_count_list.sort(key = lambda i: i[2])\n", + " for row in to_count_list:\n", + " sheet.append(row)\n", + " \n", + " tab = Table(displayName=\"Counting\", ref=f\"A1:O{len(to_count_list)+2}\")\n", + "\n", + " sheet.add_table(tab)\n", + " hlb_count.save(HLB_COUNT_PATH)\n", + "finally:\n", " hlb_count.close()" - ], - "outputs": [], - "metadata": {} + ] }, { "cell_type": "code", "execution_count": null, - "source": [], + "metadata": {}, "outputs": [], - "metadata": {} + "source": [] } ], "metadata": { "interpreter": { - "hash": "032eb40c1682b1e6109824d577ff4427b0bbc2f8ebe1487b7b1be524c4843266" + "hash": "2be5faf79681da6f2a61fdfdd5405d65d042280f7fba6178067603e3a2925119" }, "kernelspec": { - "name": "python3", - "display_name": "Python 3.9.7 64-bit" + "display_name": "Python 3.10.0 64-bit", + "name": "python3" }, "language_info": { - "name": "python", - "version": "3.9.7", - "mimetype": "text/x-python", "codemirror_mode": { "name": "ipython", "version": 3 }, - "pygments_lexer": "ipython3", + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", "nbconvert_exporter": "python", - "file_extension": ".py" + "pygments_lexer": "ipython3", + "version": "3.10.1" }, "metadata": { "interpreter": { @@ -1360,4 +1434,4 @@ }, "nbformat": 4, "nbformat_minor": 2 -} \ No newline at end of file +}