Deaktiviere Pre-Commit temporär

pull/94/head
Abdulrahman Dabbagh 2025-06-29 11:09:11 +02:00
parent 360da3acb0
commit 6c55150e9c
11 changed files with 119 additions and 42 deletions

View File

@ -34,6 +34,7 @@ def create_kpi_setting():
"position",
"active",
"examples",
"is_trained",
]
for field in required_fields:
if field not in data:
@ -58,6 +59,7 @@ def create_kpi_setting():
position=data["position"],
active=data["active"],
examples=data.get("examples", []),
is_trained=False
)
db.session.add(new_kpi_setting)

View File

@ -6,6 +6,8 @@ from werkzeug.utils import secure_filename
from model.database import db
import os
import requests
from model.kpi_setting_model import KPISettingModel
spacy_controller = Blueprint("spacy", __name__, url_prefix="/api/spacy")
@ -122,8 +124,14 @@ current_training_status = {"running": False}
def update_training_status():
data = request.get_json()
current_training_status["running"] = data.get("running", False)
running = current_training_status["running"]
print(f"[INFO] Trainingsstatus aktualisiert: running = {running}")
if current_training_status["running"] is False:
try:
KPISettingModel.query.update({KPISettingModel.is_trained: True})
db.session.commit()
except Exception as e:
db.session.rollback()
return jsonify({"error": "is_trained konnte nicht aktualisiert werden", "details": str(e)}), 500
return jsonify({"status": "success", "running": current_training_status["running"]})

View File

@ -27,6 +27,8 @@ class KPISettingModel(db.Model):
position: Mapped[int]
active: Mapped[bool]
examples: Mapped[list] = mapped_column(JSONB, default=[])
is_trained: Mapped[bool] = mapped_column(default=False)
def to_dict(self):
return OrderedDict(
@ -38,13 +40,15 @@ class KPISettingModel(db.Model):
("position", self.position),
("examples", self.examples),
("active", self.active),
("is_trained", self.is_trained),
]
)
def __init__(self, name, mandatory, type, position, active, examples=None):
def __init__(self, name, mandatory, type, position, active, examples=None, is_trained=False):
self.name = name
self.mandatory = mandatory
self.type = type
self.position = position
self.active = active
self.examples = examples or []
self.is_trained = is_trained

View File

@ -14,6 +14,7 @@ def seed_default_kpi_settings():
"type": KPISettingType.STRING,
"position": 1,
"active": True,
"is_trained": True,
"examples": [
{
"sentence": "Der Fonds trägt den Namen Alpha Real Estate Fund I.",
@ -31,6 +32,7 @@ def seed_default_kpi_settings():
"type": KPISettingType.STRING,
"position": 2,
"active": True,
"is_trained": True,
"examples": [
{
"sentence": "Fondsmanager des Projekts ist Max Mustermann.",
@ -48,6 +50,7 @@ def seed_default_kpi_settings():
"type": KPISettingType.STRING,
"position": 3,
"active": True,
"is_trained": True,
"examples": [
{
"sentence": "AIFM ist die Alpha Investment Management GmbH.",
@ -65,6 +68,7 @@ def seed_default_kpi_settings():
"type": KPISettingType.DATE,
"position": 4,
"active": True,
"is_trained": True,
"examples": [
{
"sentence": "Die Daten basieren auf dem Stand vom 05.05.2025.",
@ -82,6 +86,7 @@ def seed_default_kpi_settings():
"type": KPISettingType.STRING,
"position": 5,
"active": True,
"is_trained": True,
"examples": [
{
"sentence": "Der Fonds hat das Risikoprofil Core/Core++.",
@ -99,6 +104,7 @@ def seed_default_kpi_settings():
"type": KPISettingType.BOOLEAN,
"position": 6,
"active": True,
"is_trained": True,
"examples": [
{
"sentence": "Der Fonds erfüllt die Anforderungen von Artikel 8.",
@ -116,6 +122,7 @@ def seed_default_kpi_settings():
"type": KPISettingType.NUMBER,
"position": 7,
"active": True,
"is_trained": True,
"examples": [
{
"sentence": "Die angestrebte Zielrendite liegt bei 6.5%.",
@ -130,6 +137,7 @@ def seed_default_kpi_settings():
"type": KPISettingType.NUMBER,
"position": 8,
"active": True,
"is_trained": True,
"examples": [
{
"sentence": "Die Rendite für das Jahr beträgt 5.8%.",
@ -147,6 +155,7 @@ def seed_default_kpi_settings():
"type": KPISettingType.NUMBER,
"position": 9,
"active": True,
"is_trained": True,
"examples": [
{"sentence": "Die Zielausschüttung beträgt 4.0%.", "value": "4.0%"},
{
@ -161,6 +170,7 @@ def seed_default_kpi_settings():
"type": KPISettingType.NUMBER,
"position": 10,
"active": True,
"is_trained": True,
"examples": [
{
"sentence": "Die Ausschüttung im Jahr 2024 lag bei 3.8%.",
@ -178,6 +188,7 @@ def seed_default_kpi_settings():
"type": KPISettingType.STRING,
"position": 11,
"active": True,
"is_trained": True,
"examples": [
{
"sentence": "Die Laufzeit des Fonds beträgt 7 Jahre.",
@ -192,6 +203,7 @@ def seed_default_kpi_settings():
"type": KPISettingType.NUMBER,
"position": 12,
"active": True,
"is_trained": True,
"examples": [
{"sentence": "Der LTV beträgt 65.0%.", "value": "65.0%"},
{"sentence": "Loan-to-Value-Ratio: 65.0%.", "value": "65.0%"},
@ -203,6 +215,7 @@ def seed_default_kpi_settings():
"type": KPISettingType.NUMBER,
"position": 13,
"active": True,
"is_trained": True,
"examples": [
{
"sentence": "Die Managementgebühren betragen jährlich 1.5%.",
@ -220,6 +233,7 @@ def seed_default_kpi_settings():
"type": KPISettingType.ARRAY,
"position": 14,
"active": True,
"is_trained": True,
"examples": [
{
"sentence": "Die Sektorenallokation umfasst Büro, Wohnen und Logistik.",
@ -237,6 +251,7 @@ def seed_default_kpi_settings():
"type": KPISettingType.ARRAY,
"position": 15,
"active": True,
"is_trained": True,
"examples": [
{
"sentence": "Investitionen erfolgen in Deutschland, Frankreich und Österreich.",
@ -260,6 +275,7 @@ def seed_default_kpi_settings():
position=kpi_data["position"],
active=kpi_data["active"],
examples=kpi_data.get("examples", []),
is_trained=kpi_data["is_trained"],
)
db.session.add(kpi_setting)
@ -273,3 +289,4 @@ def seed_default_kpi_settings():
db.session.rollback()
print(f"Fehler beim Hinzufügen der Standard KPI Settings: {e}")
raise

View File

@ -1394,7 +1394,6 @@
"across",
"act",
"active",
"adasd23",
"add",
"adv",
"adv.",
@ -1684,7 +1683,7 @@
"d.h",
"d.h.",
"d.x",
"d23",
"d34",
"dX",
"dXxx.\u20ac",
"d_d",
@ -1758,6 +1757,7 @@
"dr.",
"drawbacks",
"driven",
"dsadad34",
"dte",
"du",
"dual",
@ -1914,6 +1914,7 @@
"e\u2019s",
"f",
"f.",
"f45",
"fa",
"fa.",
"faktor",
@ -1929,6 +1930,7 @@
"festgelegt",
"festgelegter",
"ff",
"fh5",
"fierce",
"fil",
"financially",
@ -2026,6 +2028,8 @@
"ggfs.",
"gg\u00fc",
"gg\u00fc.",
"ghgh56",
"ghghgwef45",
"ght",
"gic",
"gie",
@ -2050,6 +2054,7 @@
"h.",
"h.c",
"h.c.",
"h56",
"haltedauer",
"halten",
"halten-strategie",
@ -2073,6 +2078,7 @@
"her",
"here",
"hes",
"hewhfh5",
"hf.",
"hg",
"hg.",
@ -2260,6 +2266,7 @@
"jeweiliges",
"jh",
"jh.",
"jhchewqc7",
"jhd",
"jhd.",
"jor",
@ -2293,9 +2300,11 @@
"key",
"kindertagesst\u00e4tte",
"kingdom",
"kkn7",
"kl.",
"klassifikation",
"klassifizierung",
"kn7",
"kontinentaleuropaische",
"kosten",
"kt-",
@ -2693,6 +2702,7 @@
"q.",
"q.e.d",
"q.e.d.",
"qc7",
"quality",
"quarterly",
"quota",
@ -2791,12 +2801,14 @@
"sa.",
"sale",
"sb.",
"sc3",
"schule",
"schweden",
"scope",
"scs",
"scsp",
"sd.",
"sdcdsc3",
"sector",
"sectors",
"sed",
@ -3128,12 +3140,14 @@
"xxx-Xxxxx",
"xxx-xxxx",
"xxx.",
"xxxd",
"xxxx",
"xxxx+",
"xxxx-xx",
"xxxx-xxx",
"xxxx-xxxx",
"xxxx.",
"xxxxd",
"xxxxdd",
"xxxx\u2019x",
"xxx\u2019x",

View File

@ -6,41 +6,56 @@ import type { Kennzahl } from "../types/kpi";
import { getDisplayType } from "../types/kpi";
import { fetchKennzahlen as fetchK } from "../util/api";
import { API_HOST } from "../util/api";
import WarningAmberIcon from "@mui/icons-material/WarningAmber";
type ConfigTableProps = {
export type ConfigTableProps = {
from?: string;
trainingRunning?: boolean;
};
export function ConfigTable({ from }: ConfigTableProps) {
export function ConfigTable({ from, trainingRunning }: ConfigTableProps) {
const navigate = useNavigate();
const [kennzahlen, setKennzahlen] = useState<Kennzahl[]>([]);
const [draggedItem, setDraggedItem] = useState<Kennzahl | null>(null);
const [isUpdatingPositions, setIsUpdatingPositions] = useState(false);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchKennzahlen = async () => {
while (true) {
try {
console.log("Fetching kennzahlen from API...");
const data = await fetchK();
console.log("Fetched kennzahlen:", data);
const sortedData = data.sort(
(a: Kennzahl, b: Kennzahl) => a.position - b.position,
);
setKennzahlen(sortedData);
setLoading(false);
break;
} catch (err) {
console.error("Error fetching kennzahlen:", err);
await new Promise((resolve) => setTimeout(resolve, 2000));
}
const fetchKennzahlen = async () => {
while (true) {
try {
console.log("Fetching kennzahlen from API...");
const data = await fetchK();
console.log("Fetched kennzahlen:", data);
const sortedData = data.sort((a, b) => a.position - b.position);
setKennzahlen(sortedData);
setLoading(false);
break;
} catch (err) {
console.error("Error fetching kennzahlen:", err);
await new Promise((resolve) => setTimeout(resolve, 2000));
}
};
}
};
useEffect(() => {
fetchKennzahlen();
}, []);
useEffect(() => {
if (trainingRunning === false) {
console.log("[ConfigTable] Training beendet → Kennzahlen neu laden...");
fetchKennzahlen();
}
}, [trainingRunning]);
const handleToggleActive = async (id: number) => {
const kennzahl = kennzahlen.find((k) => k.id === id);
if (!kennzahl) return;
@ -326,15 +341,32 @@ export function ConfigTable({ from }: ConfigTableProps) {
padding: "12px",
fontSize: "14px",
color: "#333",
display: "flex",
alignItems: "center",
gap: "8px",
}}
>
<span title={`Click to view details (ID: ${kennzahl.id})`}>
{kennzahl.name}
{kennzahl.mandatory && (
<span> *</span>
)}
{kennzahl.mandatory && <span> *</span>}
</span>
{kennzahl.is_trained === false && (
<Tooltip
title={
<>
<b>Diese Kennzahl ist nicht trainiert.</b><br />
Klicken Sie oben auf <i>"Neu trainieren"</i>, um das Training zu starten.
</>
}
arrow
placement="right"
>
<WarningAmberIcon sx={{ color: "#f57c00", fontSize: 20 }} />
</Tooltip>
)}
</td>
<td style={{ padding: "12px" }}>
<span
style={{

View File

@ -20,11 +20,8 @@ interface KPIFormProps {
const emptyKPI: Partial<Kennzahl> = {
name: '',
description: '',
mandatory: false,
type: 'string',
translation: '',
example: '',
active: true,
examples: [{ sentence: '', value: '' }],
};
@ -115,26 +112,24 @@ export function KPIForm({ mode, initialData, onSave, onCancel, loading = false,
// Dann in die DB speichern
await onSave({
name: formData.name!,
description: formData.description || '',
mandatory: formData.mandatory ?? false,
type: formData.type || 'string',
translation: formData.translation || '',
example: formData.example || '',
position: formData.position ?? 0,
active: formData.active ?? true,
examples: formData.examples ?? []
examples: formData.examples ?? [],
is_trained: false,
});
// Formular zurücksetzen:
setFormData(emptyKPI);
setSnackbarMessage("Beispielsätze gespeichert. Jetzt auf Neu trainieren klicken oder weitere Kennzahlen hinzufügen.");
setSnackbarMessage("Beispielsätze gespeichert. Jetzt auf -Neu trainieren- klicken oder weitere Kennzahlen hinzufügen.");
setSnackbarSeverity("success");
setSnackbarOpen(true);
} catch (e: any) {
// Prüfe auf 409-Fehler
if (e?.message?.includes("409") || e?.response?.status === 409) {
setSnackbarMessage("Diese Kennzahl existiert bereits. Sie können sie unter Konfiguration bearbeiten.");
setSnackbarMessage("Diese Kennzahl existiert bereits. Sie können sie unter -Konfiguration- bearbeiten.");
setSnackbarSeverity("info");
setSnackbarOpen(true);
} else {

View File

@ -165,12 +165,16 @@ function ConfigPage() {
}}
>
{trainingRunning ? (
<CircularProgress size={24} sx={{ color: "white" }} />
<>
<CircularProgress size={20} sx={{ color: "white", mr: 1 }} />
Wird trainiert...
</>
) : (
"Neu trainieren"
)}
</Button>
<Button
variant="contained"
onClick={handleAddNewKPI}
@ -186,7 +190,7 @@ function ConfigPage() {
{/* Tabelle */}
<Box sx={{ width: "100%", mt: 4, display: "flex", justifyContent: "center" }}>
<ConfigTable from={from} />
<ConfigTable from={from} trainingRunning={trainingRunning} />
</Box>
</Box>

View File

@ -1,11 +1,8 @@
export interface Kennzahl {
id: number;
name: string;
description: string;
mandatory: boolean;
type: string;
translation: string;
example: string;
position: number;
active: boolean;
exampleText?: string;
@ -14,6 +11,7 @@ export interface Kennzahl {
sentence: string;
value: string;
}[];
is_trained?: boolean;
}
export const typeDisplayMapping: Record<string, string> = {

View File

@ -5,6 +5,9 @@ import { defineConfig } from "vite";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [TanStackRouterVite({ autoCodeSplitting: true }), viteReact()],
build: {
chunkSizeWarningLimit: 1000, // default ist 500
},
test: {
globals: true,
environment: "jsdom",