|
|
|
|
@ -1,5 +1,7 @@
|
|
|
|
|
import os
|
|
|
|
|
import io
|
|
|
|
|
import sqlite3
|
|
|
|
|
import re
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
|
|
|
|
import pandas as pd
|
|
|
|
|
@ -7,12 +9,11 @@ from dotenv import load_dotenv
|
|
|
|
|
from flask import Flask, request, render_template, redirect, url_for, flash, Response
|
|
|
|
|
from werkzeug.utils import secure_filename
|
|
|
|
|
|
|
|
|
|
from database import get_db_connection
|
|
|
|
|
|
|
|
|
|
env_path = "./.env"
|
|
|
|
|
load_dotenv(env_path)
|
|
|
|
|
|
|
|
|
|
UPLOAD_FOLDER = os.getenv("UPLOAD_FOLDER")
|
|
|
|
|
UPLOAD_FOLDER = os.getenv("UPLOAD_FOLDER", "uploads")
|
|
|
|
|
DATABASE = "data.db"
|
|
|
|
|
ALLOWED_EXTENSIONS = {"xlsx"}
|
|
|
|
|
|
|
|
|
|
app = Flask(__name__)
|
|
|
|
|
@ -20,10 +21,74 @@ app.config["UPLOAD_FOLDER"] = UPLOAD_FOLDER
|
|
|
|
|
app.secret_key = "9f2a1d3e4c5b6a7d8e9f0a1b2c3d4e5f"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def init_db():
|
|
|
|
|
with sqlite3.connect(DATABASE) as conn:
|
|
|
|
|
cursor = conn.cursor()
|
|
|
|
|
cursor.execute("""
|
|
|
|
|
CREATE TABLE IF NOT EXISTS onderhoud (
|
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
|
|
Object_code TEXT,
|
|
|
|
|
Object_omschrijving TEXT,
|
|
|
|
|
Afdeling_object TEXT,
|
|
|
|
|
PO_Code TEXT,
|
|
|
|
|
Omschrijving_PO TEXT,
|
|
|
|
|
Vervaldatum TEXT,
|
|
|
|
|
Frequentie INTEGER,
|
|
|
|
|
UOM TEXT,
|
|
|
|
|
PO_schema_Niet_gebruikt TEXT,
|
|
|
|
|
Cluster TEXT,
|
|
|
|
|
Locatie TEXT,
|
|
|
|
|
Locatie_omschrijving TEXT,
|
|
|
|
|
Klasse_object TEXT,
|
|
|
|
|
Categorie TEXT
|
|
|
|
|
)
|
|
|
|
|
""")
|
|
|
|
|
conn.commit()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def allowed_file(filename):
|
|
|
|
|
return "." in filename and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.route("/download", methods=["GET"])
|
|
|
|
|
def download_excel():
|
|
|
|
|
x_str = request.args.get("x")
|
|
|
|
|
if not x_str:
|
|
|
|
|
flash("Geen datum opgegeven voor download.", "danger")
|
|
|
|
|
return redirect(url_for("upload_file"))
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
x = datetime.strptime(x_str, "%Y-%m-%d")
|
|
|
|
|
except ValueError:
|
|
|
|
|
flash("Ongeldige datum opgegeven.", "danger")
|
|
|
|
|
return redirect(url_for("upload_file"))
|
|
|
|
|
|
|
|
|
|
result = get_extrapolation(x)
|
|
|
|
|
|
|
|
|
|
if not result:
|
|
|
|
|
flash("Geen resultaten beschikbaar voor de geselecteerde datum.", "warning")
|
|
|
|
|
return redirect(url_for("upload_file"))
|
|
|
|
|
|
|
|
|
|
df = pd.DataFrame(result)
|
|
|
|
|
|
|
|
|
|
# Verwijder de Vervaldatum kolom
|
|
|
|
|
if 'Vervaldatum' in df.columns:
|
|
|
|
|
df = df.drop(columns=['Vervaldatum'])
|
|
|
|
|
# df.rename(columns={"Begindatum": "Vervaldatum"}, inplace=True)
|
|
|
|
|
output = io.BytesIO()
|
|
|
|
|
with pd.ExcelWriter(output, engine="openpyxl") as writer:
|
|
|
|
|
df.to_excel(writer, index=False,
|
|
|
|
|
sheet_name=f"Extrapolatie_{x.strftime('%Y-%m-%d')}")
|
|
|
|
|
output.seek(0)
|
|
|
|
|
|
|
|
|
|
filename = f"extrapolatie_{x.strftime('%Y-%m-%d')}.xlsx"
|
|
|
|
|
return Response(
|
|
|
|
|
output,
|
|
|
|
|
mimetype="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
|
|
|
headers={"Content-Disposition": f"attachment; filename={filename}"}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.route("/", methods=["GET", "POST"])
|
|
|
|
|
def upload_file():
|
|
|
|
|
if request.method == "POST":
|
|
|
|
|
@ -41,102 +106,77 @@ def upload_file():
|
|
|
|
|
filepath = os.path.join(app.config["UPLOAD_FOLDER"], filename)
|
|
|
|
|
file.save(filepath)
|
|
|
|
|
process_excel(filepath)
|
|
|
|
|
flash(
|
|
|
|
|
"Bestand geüpload en verwerkt! <a href='" +
|
|
|
|
|
url_for("show_result") + "'>Bekijk de resultaten</a>",
|
|
|
|
|
"success",
|
|
|
|
|
)
|
|
|
|
|
flash("Bestand geüpload en verwerkt! <a href='" +
|
|
|
|
|
url_for("show_result") + "'>Bekijk de resultaten</a>", "success")
|
|
|
|
|
return redirect(url_for("upload_file"))
|
|
|
|
|
|
|
|
|
|
return render_template("index.html")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.route("/extrapolate", methods=["GET", "POST"])
|
|
|
|
|
def show_result():
|
|
|
|
|
x_str = request.form.get("selected_date")
|
|
|
|
|
print(x_str)
|
|
|
|
|
try:
|
|
|
|
|
if x_str is not None:
|
|
|
|
|
x = datetime.strptime(x_str, "%Y-%m-%d")
|
|
|
|
|
else:
|
|
|
|
|
# Handle the case where x_str is None, for example:
|
|
|
|
|
x = None # or raise an exception or use a default date
|
|
|
|
|
flash("Ongeldige datum ingevoerd.", "danger")
|
|
|
|
|
except ValueError:
|
|
|
|
|
flash("Ongeldige datum ingevoerd.", "danger")
|
|
|
|
|
return redirect(url_for("upload_file"))
|
|
|
|
|
|
|
|
|
|
result = getextrapolation(x)
|
|
|
|
|
return render_template("resultaat.html", result=result, selected_date=x_str)
|
|
|
|
|
@app.route("/debug_db", methods=["GET"])
|
|
|
|
|
def debug_db():
|
|
|
|
|
with sqlite3.connect(DATABASE) as conn:
|
|
|
|
|
cursor = conn.cursor()
|
|
|
|
|
cursor.execute("SELECT * FROM onderhoud")
|
|
|
|
|
columns = [desc[0] for desc in cursor.description]
|
|
|
|
|
rows = cursor.fetchall()
|
|
|
|
|
|
|
|
|
|
return render_template("debug.html", columns=columns, rows=rows)
|
|
|
|
|
|
|
|
|
|
@app.route("/download", methods=["GET"])
|
|
|
|
|
def download_excel():
|
|
|
|
|
x_str = request.args.get("x")
|
|
|
|
|
x = datetime.strptime(x_str, "%Y-%m-%d")
|
|
|
|
|
result = getextrapolation(x)
|
|
|
|
|
|
|
|
|
|
df = pd.DataFrame(result)
|
|
|
|
|
output = io.BytesIO()
|
|
|
|
|
with pd.ExcelWriter(output, engine="openpyxl") as writer:
|
|
|
|
|
df.to_excel(writer, index=False,
|
|
|
|
|
sheet_name=f"Extrapolatie_{x.strftime('%Y-%m-%d')}")
|
|
|
|
|
output.seek(0)
|
|
|
|
|
|
|
|
|
|
filename = f"extrapolatie_{x.strftime('%Y-%m-%d')}.xlsx"
|
|
|
|
|
return Response(
|
|
|
|
|
output,
|
|
|
|
|
mimetype="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
|
|
|
headers={"Content-Disposition": f"attachment; filename={filename}"},
|
|
|
|
|
)
|
|
|
|
|
def clean_column_name(name):
|
|
|
|
|
# Vervangt alle niet-alfanumerieke tekens door "_"
|
|
|
|
|
return re.sub(r"\W+", "_", name)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def extrapolate_vervaldatum(vervaldatum, uom, frequentie, x):
|
|
|
|
|
if vervaldatum is None or pd.isna(vervaldatum):
|
|
|
|
|
print("Ongeldige vervaldatum:", vervaldatum)
|
|
|
|
|
return [] # Geef een lege lijst terug in plaats van een fout te veroorzaken
|
|
|
|
|
def process_excel(filepath):
|
|
|
|
|
df = pd.read_excel(filepath)
|
|
|
|
|
# Kolomnamen normaliseren
|
|
|
|
|
df.columns = [clean_column_name(col) for col in df.columns]
|
|
|
|
|
|
|
|
|
|
vervaldatum = pd.to_datetime(str(vervaldatum), errors="coerce")
|
|
|
|
|
with sqlite3.connect(DATABASE) as conn:
|
|
|
|
|
cursor = conn.cursor()
|
|
|
|
|
cursor.execute("DELETE FROM onderhoud") # Leeg de tabel eerst
|
|
|
|
|
df.to_sql("onderhoud", conn, if_exists="append", index=False)
|
|
|
|
|
|
|
|
|
|
if pd.isna(vervaldatum): # Extra controle als de conversie mislukt
|
|
|
|
|
print("Kon datum niet omzetten:", vervaldatum)
|
|
|
|
|
return []
|
|
|
|
|
# Debug: Controleer of de records echt zijn toegevoegd
|
|
|
|
|
cursor.execute("SELECT COUNT(*) FROM onderhoud")
|
|
|
|
|
count = cursor.fetchone()[0]
|
|
|
|
|
# Controleer of data correct is ingevoerd
|
|
|
|
|
print(f"Aantal records in de database: {count}")
|
|
|
|
|
|
|
|
|
|
result = []
|
|
|
|
|
|
|
|
|
|
while vervaldatum <= x:
|
|
|
|
|
result.append(vervaldatum.strftime("%Y-%m-%d"))
|
|
|
|
|
@app.route("/extrapolate", methods=["GET", "POST"])
|
|
|
|
|
def show_result():
|
|
|
|
|
# Haal de huidige datum op voor de standaardwaarde
|
|
|
|
|
today = datetime.today().strftime('%Y-%m-%d')
|
|
|
|
|
|
|
|
|
|
if uom == "D":
|
|
|
|
|
vervaldatum += pd.DateOffset(days=frequentie)
|
|
|
|
|
elif uom == "W":
|
|
|
|
|
vervaldatum += pd.DateOffset(weeks=frequentie)
|
|
|
|
|
elif uom == "M":
|
|
|
|
|
vervaldatum += pd.DateOffset(months=frequentie)
|
|
|
|
|
elif uom == "Y":
|
|
|
|
|
vervaldatum += pd.DateOffset(years=frequentie)
|
|
|
|
|
else:
|
|
|
|
|
print("Onbekende eenheid:", uom)
|
|
|
|
|
break # Voorkom oneindige lus bij een onbekende eenheid
|
|
|
|
|
x_str = request.form.get("selected_date")
|
|
|
|
|
try:
|
|
|
|
|
x = datetime.strptime(x_str, "%Y-%m-%d") if x_str else datetime.today()
|
|
|
|
|
except ValueError:
|
|
|
|
|
flash("Ongeldige datum ingevoerd.", "danger")
|
|
|
|
|
return redirect(url_for("upload_file"))
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
result = get_extrapolation(x)
|
|
|
|
|
return render_template("resultaat.html", result=result, selected_date=x_str, today=today)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def getextrapolation(x):
|
|
|
|
|
def get_extrapolation(x):
|
|
|
|
|
if x is None:
|
|
|
|
|
print("Geen geldige datum opgegeven voor extrapolatie.")
|
|
|
|
|
return []
|
|
|
|
|
conn, cursor = get_db_connection()
|
|
|
|
|
cursor.execute("""
|
|
|
|
|
SELECT Object_code, Object_omschrijving, Afdeling_object, PO_Code, Omschrijving_PO, Vervaldatum, Frequentie, UOM,
|
|
|
|
|
PO_schema_Niet_gebruikt, Cluster, Locatie, Locatie_omschrijving, Klasse_object, Categorie
|
|
|
|
|
FROM onderhoud
|
|
|
|
|
""")
|
|
|
|
|
|
|
|
|
|
columns = [desc[0] for desc in cursor.description]
|
|
|
|
|
rows = cursor.fetchall()
|
|
|
|
|
cursor.close()
|
|
|
|
|
conn.close()
|
|
|
|
|
|
|
|
|
|
today = datetime.today()
|
|
|
|
|
with sqlite3.connect(DATABASE) as conn:
|
|
|
|
|
cursor = conn.cursor()
|
|
|
|
|
cursor.execute("""
|
|
|
|
|
SELECT Object_code, Object_omschrijving, Afdeling_object, PO_Code, Omschrijving_PO,
|
|
|
|
|
Vervaldatum, Frequentie, UOM, PO_schema_Niet_gebruikt, Cluster, Locatie,
|
|
|
|
|
Locatie_omschrijving, Klasse_object, Categorie
|
|
|
|
|
FROM onderhoud
|
|
|
|
|
""")
|
|
|
|
|
columns = [desc[0] for desc in cursor.description]
|
|
|
|
|
rows = cursor.fetchall()
|
|
|
|
|
|
|
|
|
|
raw_data = [dict(zip(columns, row)) for row in rows]
|
|
|
|
|
result = []
|
|
|
|
|
@ -149,14 +189,51 @@ def getextrapolation(x):
|
|
|
|
|
if vervaldatum:
|
|
|
|
|
extrapolated_dates = extrapolate_vervaldatum(
|
|
|
|
|
vervaldatum, uom, frequentie, x)
|
|
|
|
|
for date in extrapolated_dates:
|
|
|
|
|
for i, date in enumerate(extrapolated_dates):
|
|
|
|
|
new_row = row.copy()
|
|
|
|
|
new_row["Vervaldatum"] = date
|
|
|
|
|
begindatum = pd.to_datetime(date)
|
|
|
|
|
if begindatum <= today:
|
|
|
|
|
new_row["Overtijd"] = "Ja"
|
|
|
|
|
else:
|
|
|
|
|
new_row["Overtijd"] = "Nee"
|
|
|
|
|
new_row["Begindatum"] = date
|
|
|
|
|
|
|
|
|
|
if i == 0:
|
|
|
|
|
new_row["Parent"] = "*"
|
|
|
|
|
else:
|
|
|
|
|
new_row["Parent"] = ""
|
|
|
|
|
|
|
|
|
|
result.append(new_row)
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def extrapolate_vervaldatum(vervaldatum, uom, frequentie, x):
|
|
|
|
|
vervaldatum = pd.to_datetime(str(vervaldatum), errors="coerce")
|
|
|
|
|
if pd.isna(vervaldatum):
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
|
|
result = []
|
|
|
|
|
while vervaldatum <= x:
|
|
|
|
|
result.append(vervaldatum.strftime("%Y-%m-%d"))
|
|
|
|
|
if uom == "D":
|
|
|
|
|
vervaldatum += pd.DateOffset(days=frequentie)
|
|
|
|
|
# vervaldatum += pd.DateOffset(weeks=frequentie // 7)
|
|
|
|
|
# vervaldatum += pd.DateOffset(months=frequentie // 30)
|
|
|
|
|
elif uom == "W":
|
|
|
|
|
vervaldatum += pd.DateOffset(weeks=frequentie)
|
|
|
|
|
elif uom == "M":
|
|
|
|
|
vervaldatum += pd.DateOffset(months=frequentie)
|
|
|
|
|
elif uom == "Y":
|
|
|
|
|
vervaldatum += pd.DateOffset(years=frequentie)
|
|
|
|
|
else:
|
|
|
|
|
break
|
|
|
|
|
if vervaldatum > x:
|
|
|
|
|
break
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
|
|
|
|
|
init_db()
|
|
|
|
|
app.run(debug=True)
|
|
|
|
|
|