delfland ppo-extrapolate

celery-integration
peter.fong 9 months ago
parent 1a32b70a2f
commit dcffd3658c

@ -0,0 +1,36 @@
# Gebruik een officiële Python-image als basis
FROM python:3.9-slim
RUN apt-get update && apt-get -y install cron nano procps libmariadb-dev
# Werkdirectory instellen
WORKDIR /app
# Kopieer je Python-bestanden naar de container
COPY . /app
# Kopieer de requirements.txt naar de container
COPY requirements.txt .
# Kopieer de requirements.txt naar de container
COPY .env .
# Installeer de vereiste Python dependencies
RUN pip install --no-cache-dir -r requirements.txt
# Installeer cron en zorg ervoor dat de cron-demon actief is
RUN apt-get update && apt-get install -y cron
# Voeg het cron-script toe
COPY cronfile.energie /etc/cron.d/cronfile.energie
# Zorg ervoor dat het cron-script uitvoerbaar is
RUN chmod 0644 /etc/cron.d/cronfile.energie
# Voeg een cronjob toe die de Python-script dagelijks uitvoert
RUN crontab /etc/cron.d/cronfile.energie
# Voeg start.sh toe
COPY start.sh /start.sh
RUN chmod +x /start.sh
# Gebruik start.sh om zowel cron als currentprice.py te starten
CMD ["/start.sh"]

@ -0,0 +1,18 @@
import mariadb
import os
from dotenv import load_dotenv
# Configuratie laden uit .env-bestand
load_dotenv()
def get_db_connection():
"""Maakt een verbinding met de MariaDB-database en retourneert de cursor en verbinding."""
conn = mariadb.connect(
host=os.getenv("DB_HOST"),
user=os.getenv("DB_USER"),
password=os.getenv("DB_PASSWORD"),
database=os.getenv("DB_NAME"),
port=int(os.getenv("DB_PORT"))
)
return conn, conn.cursor()

@ -0,0 +1,15 @@
# docker compose -f energyprices_docker-compose.yml up -d --build
version: "3.3"
services:
delflanddev:
restart: always
container_name: delflanddev
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Amsterdam
build:
dockerfile: ./Dockerfile
env_file:
- .env

@ -0,0 +1,226 @@
import os
import pandas as pd
from flask import Flask, request, render_template, redirect, url_for, flash
from werkzeug.utils import secure_filename
from dotenv import load_dotenv
from database import get_db_connection
from flask import Response
import io
from datetime import datetime
# Configuratie laden
env_path = "./.env"
load_dotenv(env_path)
UPLOAD_FOLDER = os.getenv("UPLOAD_FOLDER")
ALLOWED_EXTENSIONS = {"xlsx"}
app = Flask(__name__)
app.config["UPLOAD_FOLDER"] = UPLOAD_FOLDER
app.secret_key = "supersecretkey"
# Controleer of bestand toegestaan is
def allowed_file(filename):
return "." in filename and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS
# Route voor de uploadpagina
@app.route("/", methods=["GET", "POST"])
def upload_file():
if request.method == "POST":
if "file" not in request.files:
flash("Geen bestand geselecteerd", "danger")
return redirect(request.url)
file = request.files["file"]
if file.filename == "":
flash("Geen bestand geselecteerd", "danger")
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
filepath = os.path.join(app.config["UPLOAD_FOLDER"], filename)
file.save(filepath)
flash("Bestand geüpload en verwerkt! <a href='" +
url_for('show_result') + "'>Bekijk de resultaten</a>", "success")
process_excel(filepath)
return redirect(url_for("upload_file"))
return render_template("index.html")
@app.route("/extrapolate", methods=["GET", "POST"])
def show_result():
x = request.form.get("x", 1, type=int)
result = getextrapolation(x)
# Geef de resultaten door aan het HTML-template
return render_template("resultaat.html", result=result, x=x)
@app.route("/download", methods=["GET"])
def download_excel():
x = request.args.get("x", 1, type=int)
result = getextrapolation(x)
df = pd.DataFrame(result)
# Excel-bestand in-memory genereren
output = io.BytesIO()
with pd.ExcelWriter(output, engine="openpyxl") as writer:
df.to_excel(writer, index=False, sheet_name=f"Extrapolatie_{x}jaar")
output.seek(0)
# Dynamische bestandsnaam
filename = f"extrapolatie_{x}jaar.xlsx"
return Response(
output,
mimetype="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
headers={"Content-Disposition": f"attachment; filename={filename}"}
)
def getextrapolation(extrapolateYears):
conn, cursor = get_db_connection()
# Haal de originele data op zonder extrapolatie
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
""")
# Haal de kolomnamen op
columns = [desc[0] for desc in cursor.description]
# Haal de ruwe data op
rows = cursor.fetchall()
# Sluit de cursor en de verbinding
cursor.close()
conn.close()
raw_data = [dict(zip(columns, row)) for row in rows]
# Huidige datum als pd.Timestamp (zonder tijd)
today = pd.Timestamp.today().normalize()
result = []
for row in raw_data:
vervaldatum = row.get("Vervaldatum")
# Converteer de Vervaldatum correct naar pd.Timestamp (of None bij fouten)
vervaldatum = pd.to_datetime(vervaldatum, errors="coerce")
# Controleer of de datum geldig is en in het verleden ligt
if pd.notna(vervaldatum) and vervaldatum < today:
vervaldatum = today # Zet op vandaag
for i in range(extrapolateYears + 1):
new_row = row.copy()
if pd.notna(vervaldatum): # Controleer of het een geldige datum is
new_row["Vervaldatum"] = (
vervaldatum + pd.DateOffset(years=i)).strftime("%Y-%m-%d")
else:
# Indien geen geldige datum, zet als None
new_row["Vervaldatum"] = None
result.append(new_row)
return result
def process_exceld(filepath):
df = pd.read_excel(filepath, engine="openpyxl")
print(df.columns)
df.columns = df.columns.str.strip()
# for _, row in df.iterrows():
# print(row["Object_omschrijving"])
# Verwerk het Excel-bestand en sla op in MariaDB
def process_excel(filepath):
df = pd.read_excel(filepath, engine="openpyxl")
df.columns = df.columns.str.strip()
# Databaseverbinding maken
conn, cursor = get_db_connection()
# Zorg dat de tabel bestaat
cursor.execute(
"""
CREATE TABLE IF NOT EXISTS onderhoud (
id INT AUTO_INCREMENT PRIMARY KEY,
Object_code VARCHAR(50),
Object_omschrijving TEXT,
Afdeling_object VARCHAR(100),
PO_Code VARCHAR(50),
Omschrijving_PO TEXT,
Vervaldatum DATE,
Frequentie INT,
UOM TEXT,
PO_schema_Niet_gebruikt TEXT,
Cluster TEXT,
Locatie TEXT,
Locatie_omschrijving TEXT,
Klasse_object TEXT,
Categorie TEXT
)
"""
)
# Data in de database invoegen
for _, row in df.iterrows():
for column in row.index:
if pd.isna(row[column]):
row[column] = ""
cursor.execute(
"""
INSERT INTO onderhoud
(Object_code, Object_omschrijving, Afdeling_object, PO_Code, Omschrijving_PO, Vervaldatum, Frequentie,
UOM, PO_schema_Niet_gebruikt, Cluster, Locatie, Locatie_omschrijving, Klasse_object, Categorie)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
row["Object code"],
row["Object omschrijving"],
row["Afdeling object"],
row["PO Code"],
row["Omschrijving PO"],
row["Vervaldatum"],
row["Frequentie"],
row["UOM"],
row["PO-schema Niet gebruikt"],
row["Cluster"],
row["Locatie"],
row["Locatie omschrijving"],
row["Klasse object"],
row["Categorie"],
),
)
conn.commit()
cursor.close()
conn.close()
if __name__ == "__main__":
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
app.run(debug=True)

@ -0,0 +1,6 @@
flask
python-dotenv
pandas
mariadb
openpyxl
werkzeug

@ -0,0 +1,10 @@
#!/bin/bash
# Start de cron-demon
cron
# Start het Python-script currentprice.py
python /app/ppo_insight.py &
# Wacht voor altijd zodat de container draaiende blijft
tail -f /dev/null

@ -0,0 +1,45 @@
<!DOCTYPE html>
<html lang="nl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bestand Uploaden</title>
<!-- Bootstrap CSS toevoegen -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<div class="container mt-5">
<h1>Upload een bestand</h1>
<!-- Flash-meldingen weergeven -->
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<div class="alert alert-dismissible fade show mt-3" role="alert">
{% for category, message in messages %}
<div class="alert alert-{{ category }} d-flex justify-content-between align-items-center">
<span>{{ message|safe }}</span>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endfor %}
</div>
{% endif %}
{% endwith %}
<!-- Upload formulier -->
<form action="/" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="file">Kies een bestand:</label>
<input type="file" name="file" id="file" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary">Uploaden</button>
</form>
</div>
<!-- Bootstrap JS toevoegen -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>

@ -0,0 +1,88 @@
<!DOCTYPE html>
<html lang="nl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Resultaat</title>
<!-- Bootstrap CSS toevoegen -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet" />
<style>
/* Verklein de fontgrootte en de padding van de tabel */
.table-sm th, .table-sm td {
padding: 0.3rem;
font-size: 0.85rem; /* Verklein de tekst */
}
</style>
</head>
<body>
<div class="container mt-5">
<h1>Resultaten van de query</h1>
<!-- Link terug naar uploadpagina -->
<a href="{{ url_for('upload_file') }}" class="btn btn-secondary mt-3">Terug naar upload</a>
<!-- Formulier voor het instellen van x -->
<form method="POST" class="mt-3">
<div class="form-group">
<label for="x">Aantal jaren vooruitkijken (x):</label>
<input type="number" id="x" name="x" value="{{ x }}" min="1" class="form-control w-auto d-inline">
<button type="submit" class="btn btn-primary">Update</button>
</div>
</form>
<a href="{{ url_for('download_excel', x=x) }}" class="btn btn-success">
Download als Excel ({{ x }} jaar)
</a>
<!-- Resultaat Tabel -->
<table class="table table-sm table-bordered table-striped mt-3">
<thead class="thead-dark">
<tr>
<th>Object_code</th>
<th>Object_omschrijving</th>
<th>Afdeling_object</th>
<th>PO_Code</th>
<th>Omschrijving_PO</th>
<th>Vervaldatum</th>
<th>Frequentie</th>
<th>UOM</th>
<th>PO_schema_Niet_gebruikt</th>
<th>Cluster</th>
<th>Locatie</th>
<th>Locatie_omschrijving</th>
<th>Klasse_object</th>
<th>Categorie</th>
</tr>
</thead>
<tbody>
{% for row in result %}
<tr>
<td>{{ row['Object_code'] }}</td>
<td>{{ row['Object_omschrijving'] }}</td>
<td>{{ row['Afdeling_object'] }}</td>
<td>{{ row['PO_Code'] }}</td>
<td>{{ row['Omschrijving_PO'] }}</td>
<td>{{ row['Vervaldatum'] }}</td>
<td>{{ row['Frequentie'] }}</td>
<td>{{ row['UOM'] }}</td>
<td>{{ row['PO_schema_Niet_gebruikt'] }}</td>
<td>{{ row['Cluster'] }}</td>
<td>{{ row['Locatie'] }}</td>
<td>{{ row['Locatie_omschrijving'] }}</td>
<td>{{ row['Klasse_object'] }}</td>
<td>{{ row['Categorie'] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- Bootstrap JS toevoegen -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>
Loading…
Cancel
Save