Просмотр исходного кода

Einen Großteil der Anforderungen umgesetzt

gc-server3 4 недель назад
Родитель
Сommit
a807d32e63

+ 76 - 34
app/routes.py

@@ -1,11 +1,18 @@
 import io
 import io
 from datetime import datetime
 from datetime import datetime
+from pathlib import Path
+from urllib.parse import unquote, urlencode
 
 
 import pandas as pd
 import pandas as pd
 from docx import Document
 from docx import Document
 from docxtpl import DocxTemplate
 from docxtpl import DocxTemplate
 from fastapi import APIRouter, Depends, Form, HTTPException, Request, Response
 from fastapi import APIRouter, Depends, Form, HTTPException, Request, Response
-from fastapi.responses import HTMLResponse, RedirectResponse, StreamingResponse
+from fastapi.responses import (
+    FileResponse,
+    HTMLResponse,
+    RedirectResponse,
+    StreamingResponse,
+)
 from fastapi.templating import Jinja2Templates
 from fastapi.templating import Jinja2Templates
 from sqlalchemy import text
 from sqlalchemy import text
 from sqlalchemy.orm import Session
 from sqlalchemy.orm import Session
@@ -21,12 +28,17 @@ templates = Jinja2Templates(directory="templates")
 
 
 @router.get("/", response_class=HTMLResponse)
 @router.get("/", response_class=HTMLResponse)
 def index(request: Request):
 def index(request: Request):
-    return RedirectResponse(url="/forderungen")
+    return RedirectResponse(url="/login")
 
 
 
 
 @router.get("/login", response_class=HTMLResponse)
 @router.get("/login", response_class=HTMLResponse)
 def login_get(request: Request):
 def login_get(request: Request):
-    return templates.TemplateResponse("base/login.html", {"request": request})
+    return templates.TemplateResponse(request, "base/login.html", {"request": request})
+
+
+@router.get("/select", response_class=HTMLResponse)
+def select_get(request: Request):
+    return templates.TemplateResponse(request, "base/select.html", {"request": request})
 
 
 
 
 @router.post("/login")
 @router.post("/login")
@@ -51,6 +63,8 @@ def number_format(input: float) -> str:
 
 
 
 
 def date_format(input: datetime) -> str:
 def date_format(input: datetime) -> str:
+    if input is None:
+        return ""
     return input.strftime("%d.%m.%Y")
     return input.strftime("%d.%m.%Y")
 
 
 
 
@@ -58,21 +72,28 @@ templates.env.filters["number_format"] = number_format
 templates.env.filters["date_format"] = date_format
 templates.env.filters["date_format"] = date_format
 
 
 
 
-@router.get("/forderungen/liste", response_class=HTMLResponse)
-def forderungen_liste(request: Request, db: Session = Depends(get_session), limit: int = 100):
+def single_quote(text: str):
+    return "'" + unquote(text) + "'"
+
+
+@router.get("/app/forderungen/liste", response_class=HTMLResponse)
+def forderungen_liste(request: Request, db: Session = Depends(get_session), limit: int = 100, page: int = 0):
+    params = {k: v for k, v in request.query_params.items() if v != ""}
+    if len(params) < len(request.query_params):
+        return RedirectResponse(url="/app/forderungen/liste?" + urlencode(params))
     context = {
     context = {
-        "RechnungsdatumVon": {"selectedDate": "'2000-01-01T00:00:00'"},
-        "RechnungsdatumBis": {"selectedDate": "'2027-01-01T00:00:00'"},
-        "Hauptbetrieb": {"selectedOptionValue": "''"},
-        "Standort": {"selectedOptionValue": "''"},
-        "Rechnungsnummer": {"text": "''"},
-        "Kunde": {"selectedOptionValue": "''"},
-        "Verursacher": {"selectedOptionValue": "''"},
-        "Fahrzeug": {"selectedOptionValue": "''"},
-        "Staffel": {"selectedOptionValue": "''"},
-        "Mahnstufe": {"selectedOptionValue": "''"},
-        "WiedervorlageVon": {"selectedDate": "'2000-01-01T00:00:00'"},
-        "WiedervorlageBis": {"selectedDate": "'2027-01-01T00:00:00'"},
+        "RechnungsdatumVon": {"selectedDate": single_quote(params.get("RechnungsdatumVon", "2000-01-01T00:00:00"))},
+        "RechnungsdatumBis": {"selectedDate": single_quote(params.get("RechnungsdatumBis", "2027-01-01T00:00:00"))},
+        "Hauptbetrieb": {"selectedOptionValue": single_quote(params.get("Hauptbetrieb", ""))},
+        "Standort": {"selectedOptionValue": single_quote(params.get("Standort", ""))},
+        "Rechnungsnummer": {"text": single_quote(params.get("Rechnungsnummer", ""))},
+        "Kunde": {"selectedOptionValue": single_quote(params.get("Kunde", ""))},
+        "Verursacher": {"selectedOptionValue": single_quote(params.get("Verursacher", ""))},
+        "Fahrzeug": {"selectedOptionValue": single_quote(params.get("Fahrzeug", ""))},
+        "Staffel": {"selectedOptionValue": single_quote(params.get("Staffel", ""))},
+        "Mahnstufe": {"selectedOptionValue": single_quote(params.get("Mahnstufe", ""))},
+        "WiedervorlageVon": {"selectedDate": single_quote(params.get("WiedervorlageVon", "2000-01-01T00:00:00"))},
+        "WiedervorlageBis": {"selectedDate": single_quote(params.get("WiedervorlageBis", "2027-01-01T00:00:00"))},
         "BenutzerSelect": {"selectedOptionValue": "winter"},
         "BenutzerSelect": {"selectedOptionValue": "winter"},
     }
     }
     query = templates.TemplateResponse(request, "forderungen/queries/forderungen_liste.sql", context).body.decode(
     query = templates.TemplateResponse(request, "forderungen/queries/forderungen_liste.sql", context).body.decode(
@@ -104,14 +125,21 @@ def forderungen_liste(request: Request, db: Session = Depends(get_session), limi
     for filter_name, (key, value) in config.items():
     for filter_name, (key, value) in config.items():
         filters[filter_name] = {row[col_names.index(key)]: row[col_names.index(value)] for row in q}
         filters[filter_name] = {row[col_names.index(key)]: row[col_names.index(value)] for row in q}
 
 
+    q_limit = q[page * limit : (page + 1) * limit]
+
+    defaults = {}
+    for filter_name in config.keys():
+        defaults[filter_name] = unquote(request.query_params.get(filter_name, ""))
     # print(filters["Standort"])
     # print(filters["Standort"])
 
 
     return templates.TemplateResponse(
     return templates.TemplateResponse(
-        request, "forderungen/liste.html", {"request": request, "forderungen_liste": q, "filter": filters}
+        request,
+        "forderungen/liste.html",
+        {"request": request, "forderungen_liste": q_limit, "filter": filters, "defaults": defaults},
     )
     )
 
 
 
 
-@router.get("/forderungen/details/{client_db}_{document_no}", response_class=HTMLResponse)
+@router.get("/app/forderungen/details/{client_db}_{document_no}", response_class=HTMLResponse)
 def forderungen_details(
 def forderungen_details(
     request: Request, client_db: str, document_no: str, db: Session = Depends(get_session), limit: int = 100
     request: Request, client_db: str, document_no: str, db: Session = Depends(get_session), limit: int = 100
 ):
 ):
@@ -145,6 +173,8 @@ def forderungen_details(
         "betrag": "120,00",
         "betrag": "120,00",
         "faelligkeit": "23.12.1983",
         "faelligkeit": "23.12.1983",
     }
     }
+    template_context["files"] = list(Path(f"C:\\Projekte\\Reisacher-Fileserver\\{client_db}\\{document_no}").glob("*"))
+
     return templates.TemplateResponse(request, "forderungen/details.html", template_context)
     return templates.TemplateResponse(request, "forderungen/details.html", template_context)
 
 
 
 
@@ -244,28 +274,40 @@ def export_docx(id: int, db: Session = Depends(get_session)):
     )
     )
 
 
 
 
-@router.get("/export/docx")
-def export_docx2(id: int, db: Session = Depends(get_session)):
+@router.get("/app/forderungen/export/{client_db}_{document_no}/")
+def export_docx2(request: Request, client_db: str, document_no: str, db: Session = Depends(get_session)):
+    context = {
+        "appsmith": {
+            "URL": {
+                "queryParams": {
+                    "Client_DB": "'" + client_db + "'",
+                    "Document_No": "'" + document_no + "'",
+                }
+            }
+        },
+    }
+    query = templates.TemplateResponse(request, "forderungen/queries/forderung_kopf.sql", context).body.decode("utf-8")
+    q = db.execute(text(query)).fetchone()
+
     doc = DocxTemplate("templates\\forderungen\\docs\\Mahnung_AHR.docx")
     doc = DocxTemplate("templates\\forderungen\\docs\\Mahnung_AHR.docx")
+    filename = Path(
+        f"C:\\Projekte\\Reisacher-Fileserver\\{client_db}\\{document_no}\\Mahnung_{client_db}_{document_no}.docx"
+    )
+    filename.parent.mkdir(parents=True, exist_ok=True)
+
     context = {
     context = {
-        "Kunde_Name": "Robert Burghard",
+        "Kunde_Name": q.Kunde,
         "Kunde_Adresse": "Im Waldhof 14a",
         "Kunde_Adresse": "Im Waldhof 14a",
         "Kunde_PLZ": "61476",
         "Kunde_PLZ": "61476",
         "Kunde_Ort": "Kronberg",
         "Kunde_Ort": "Kronberg",
-        "Datum_heute": "25.03.2026",
-        "Kunde_Nr": "23121983",
+        "Datum_heute": datetime.now().strftime("%d.%m.%Y"),
+        "Kunde_Nr": q.Kunde.split("-")[-1].strip(),
         "Fahrzeug_Kennzeichen": "OF-RB 512",
         "Fahrzeug_Kennzeichen": "OF-RB 512",
-        "Rechnung_Nr": "2600007",
+        "Rechnung_Nr": q.Document_No,
         "Betrag_SB": "250,00",
         "Betrag_SB": "250,00",
         "Betrag_USt": "380,00",
         "Betrag_USt": "380,00",
     }
     }
     doc.render(context)
     doc.render(context)
-    # doc.save("export\\Mahnung_AHR_Burghard.docx")
-    buf = io.BytesIO()
-    doc.save(buf)
-    buf.seek(0)
-    return StreamingResponse(
-        buf,
-        media_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
-        headers={"Content-Disposition": "attachment; filename=Mahnung_Burghard.docx"},
-    )
+    doc.save(filename)
+
+    return FileResponse(filename, media_type="application/octet-stream", filename=filename.name)

+ 29 - 60
templates/base/base.html

@@ -16,10 +16,11 @@
   
   
   <script src="https://cdn.jsdelivr.net/npm/@coreui/coreui@5.6.1/dist/js/coreui.bundle.min.js"></script>
   <script src="https://cdn.jsdelivr.net/npm/@coreui/coreui@5.6.1/dist/js/coreui.bundle.min.js"></script>
   <script src="https://cdn.jsdelivr.net/npm/@coreui/icons@3.0.1/dist/cjs/index.min.js"></script>
   <script src="https://cdn.jsdelivr.net/npm/@coreui/icons@3.0.1/dist/cjs/index.min.js"></script>
-
+  <!-- Favicon icon -->
+	<link rel="icon" href="/static/assets/images/favicon.ico" type="image/x-icon">
 </head>
 </head>
 
 
-<body class="container py-3">
+<body class="container py-3" hx-boost="true">
   <!--<nav class="navbar navbar-expand-lg bg-primary">
   <!--<nav class="navbar navbar-expand-lg bg-primary">
     <div class="container-fluid">
     <div class="container-fluid">
         <a class="navbar-brand" href="#">Navbar</a>
         <a class="navbar-brand" href="#">Navbar</a>
@@ -50,28 +51,20 @@
         <button class="header-toggler" type="button"
         <button class="header-toggler" type="button"
           onclick="coreui.Sidebar.getInstance(document.querySelector('#sidebar')).toggle()"
           onclick="coreui.Sidebar.getInstance(document.querySelector('#sidebar')).toggle()"
           style="margin-inline-start: -14px;">
           style="margin-inline-start: -14px;">
-          <svg class="icon icon-lg">
-            <use xlink:href="vendors/@coreui/icons/svg/free.svg#cil-menu"></use>
-          </svg>
+          <i class="icon icon-lg cil-menu"></i>
         </button>
         </button>
         <ul class="header-nav d-none d-lg-flex">
         <ul class="header-nav d-none d-lg-flex">
-          <li class="nav-item"><a class="nav-link" href="#">Dashboard</a></li>
-          <li class="nav-item"><a class="nav-link" href="#">Users</a></li>
-          <li class="nav-item"><a class="nav-link" href="#">Settings</a></li>
+          <li class="nav-item"><a class="nav-link" href="/select">Übersicht</a></li>
+          <li class="nav-item"><a class="nav-link" href="/app/forderungen/liste">Liste</a></li>
+          <li class="nav-item"><a class="nav-link" href="#">Einstellungen</a></li>
         </ul>
         </ul>
         <ul class="header-nav ms-auto">
         <ul class="header-nav ms-auto">
           <li class="nav-item"><a class="nav-link" href="#">
           <li class="nav-item"><a class="nav-link" href="#">
-              <svg class="icon icon-lg">
-                <use xlink:href="vendors/@coreui/icons/svg/free.svg#cil-bell"></use>
-              </svg></a></li>
+              <i class="icon icon-lg cil-bell"></i></a></li>
           <li class="nav-item"><a class="nav-link" href="#">
           <li class="nav-item"><a class="nav-link" href="#">
-              <svg class="icon icon-lg">
-                <use xlink:href="vendors/@coreui/icons/svg/free.svg#cil-list-rich"></use>
-              </svg></a></li>
+              <i class="icon icon-lg cil-list-rich"></i></a></li>
           <li class="nav-item"><a class="nav-link" href="#">
           <li class="nav-item"><a class="nav-link" href="#">
-              <svg class="icon icon-lg">
-                <use xlink:href="vendors/@coreui/icons/svg/free.svg#cil-envelope-open"></use>
-              </svg></a></li>
+              <i class="icon icon-lg cil-envelope-open"></i></a></li>
         </ul>
         </ul>
         <ul class="header-nav">
         <ul class="header-nav">
           <li class="nav-item py-1">
           <li class="nav-item py-1">
@@ -80,31 +73,23 @@
           <li class="nav-item dropdown">
           <li class="nav-item dropdown">
             <button class="btn btn-link nav-link py-2 px-2 d-flex align-items-center" type="button"
             <button class="btn btn-link nav-link py-2 px-2 d-flex align-items-center" type="button"
               aria-expanded="false" data-coreui-toggle="dropdown">
               aria-expanded="false" data-coreui-toggle="dropdown">
-              <svg class="icon icon-lg theme-icon-active">
-                <use xlink:href="vendors/@coreui/icons/svg/free.svg#cil-contrast"></use>
-              </svg>
+              <i class="icon icon-lg theme-icon-active cil-contrast"></i>
             </button>
             </button>
             <ul class="dropdown-menu dropdown-menu-end" style="--cui-dropdown-min-width: 8rem;">
             <ul class="dropdown-menu dropdown-menu-end" style="--cui-dropdown-min-width: 8rem;">
               <li>
               <li>
                 <button class="dropdown-item d-flex align-items-center" type="button" data-coreui-theme-value="light">
                 <button class="dropdown-item d-flex align-items-center" type="button" data-coreui-theme-value="light">
-                  <svg class="icon icon-lg me-3">
-                    <use xlink:href="vendors/@coreui/icons/svg/free.svg#cil-sun"></use>
-                  </svg>Light
+                  <i class="icon icon-lg me-3 cil-sun"></i> Light
                 </button>
                 </button>
               </li>
               </li>
               <li>
               <li>
                 <button class="dropdown-item d-flex align-items-center" type="button" data-coreui-theme-value="dark">
                 <button class="dropdown-item d-flex align-items-center" type="button" data-coreui-theme-value="dark">
-                  <svg class="icon icon-lg me-3">
-                    <use xlink:href="vendors/@coreui/icons/svg/free.svg#cil-moon"></use>
-                  </svg>Dark
+                  <i class="icon icon-lg me-3 cil-moon"></i> Dark
                 </button>
                 </button>
               </li>
               </li>
               <li>
               <li>
                 <button class="dropdown-item d-flex align-items-center active" type="button"
                 <button class="dropdown-item d-flex align-items-center active" type="button"
                   data-coreui-theme-value="auto">
                   data-coreui-theme-value="auto">
-                  <svg class="icon icon-lg me-3">
-                    <use xlink:href="vendors/@coreui/icons/svg/free.svg#cil-contrast"></use>
-                  </svg>Auto
+                  <i class="icon icon-lg me-3 cil-contrast"></i> Auto
                 </button>
                 </button>
               </li>
               </li>
             </ul>
             </ul>
@@ -114,52 +99,36 @@
           </li>
           </li>
           <li class="nav-item dropdown"><a class="nav-link py-0 pe-0" data-coreui-toggle="dropdown" href="#"
           <li class="nav-item dropdown"><a class="nav-link py-0 pe-0" data-coreui-toggle="dropdown" href="#"
               role="button" aria-haspopup="true" aria-expanded="false">
               role="button" aria-haspopup="true" aria-expanded="false">
-              <div class="avatar avatar-md"><img class="avatar-img" src="assets/img/avatars/8.jpg" alt="user@email.com">
+              <div class="avatar avatar-md"><img class="avatar-img" src="/static/assets/img/avatars/winter.jpg" alt="winter@global-cube.de">
               </div>
               </div>
             </a>
             </a>
             <div class="dropdown-menu dropdown-menu-end pt-0">
             <div class="dropdown-menu dropdown-menu-end pt-0">
               <div class="dropdown-header bg-body-tertiary text-body-secondary fw-semibold rounded-top mb-2">Account
               <div class="dropdown-header bg-body-tertiary text-body-secondary fw-semibold rounded-top mb-2">Account
               </div><a class="dropdown-item" href="#">
               </div><a class="dropdown-item" href="#">
-                <svg class="icon me-2">
-                  <use xlink:href="vendors/@coreui/icons/svg/free.svg#cil-bell"></use>
-                </svg> Updates<span class="badge badge-sm bg-info ms-2">42</span></a><a class="dropdown-item" href="#">
-                <svg class="icon me-2">
-                  <use xlink:href="vendors/@coreui/icons/svg/free.svg#cil-envelope-open"></use>
-                </svg> Messages<span class="badge badge-sm bg-success ms-2">42</span></a><a class="dropdown-item"
+                <i class="icon me-2 cil-bell"></i> Updates<span class="badge badge-sm bg-info ms-2">42</span></a><a class="dropdown-item" href="#">
+                <i class="icon me-2 cil-envelope-open"></i> Messages<span class="badge badge-sm bg-success ms-2">42</span></a><a class="dropdown-item"
                 href="#">
                 href="#">
-                <svg class="icon me-2">
-                  <use xlink:href="vendors/@coreui/icons/svg/free.svg#cil-task"></use>
-                </svg> Tasks<span class="badge badge-sm bg-danger ms-2">42</span></a><a class="dropdown-item" href="#">
-                <svg class="icon me-2">
-                  <use xlink:href="vendors/@coreui/icons/svg/free.svg#cil-comment-square"></use>
-                </svg> Comments<span class="badge badge-sm bg-warning ms-2">42</span></a>
+                <i class="icon me-2 cil-task"></i> Tasks<span class="badge badge-sm bg-danger ms-2">42</span></a><a class="dropdown-item" href="#">
+                <i class="icon me-2 cil-comment-square"></i> Comments<span class="badge badge-sm bg-warning ms-2">42</span></a>
               <div class="dropdown-header bg-body-tertiary text-body-secondary fw-semibold my-2">
               <div class="dropdown-header bg-body-tertiary text-body-secondary fw-semibold my-2">
                 <div class="fw-semibold">Settings</div>
                 <div class="fw-semibold">Settings</div>
               </div><a class="dropdown-item" href="#">
               </div><a class="dropdown-item" href="#">
-                <svg class="icon me-2">
-                  <use xlink:href="vendors/@coreui/icons/svg/free.svg#cil-user"></use>
-                </svg> Profile</a><a class="dropdown-item" href="#">
-                <svg class="icon me-2">
-                  <use xlink:href="vendors/@coreui/icons/svg/free.svg#cil-settings"></use>
-                </svg> Settings</a><a class="dropdown-item" href="#">
-                <svg class="icon me-2">
-                  <use xlink:href="vendors/@coreui/icons/svg/free.svg#cil-credit-card"></use>
-                </svg> Payments<span class="badge badge-sm bg-secondary ms-2">42</span></a><a class="dropdown-item"
+                <i class="icon me-2 cil-user"></i> Profile</a><a class="dropdown-item" href="#">
+                <i class="icon me-2 cil-settings"></i> Settings</a><a class="dropdown-item" href="#">
+                <i class="icon me-2 cil-credit-card"></i> Payments<span class="badge badge-sm bg-secondary ms-2">42</span></a><a class="dropdown-item"
                 href="#">
                 href="#">
-                <svg class="icon me-2">
-                  <use xlink:href="vendors/@coreui/icons/svg/free.svg#cil-file"></use>
-                </svg> Projects<span class="badge badge-sm bg-primary ms-2">42</span></a>
+                <i class="icon me-2 cil-file"></i> Projects<span class="badge badge-sm bg-primary ms-2">42</span></a>
               <div class="dropdown-divider"></div><a class="dropdown-item" href="#">
               <div class="dropdown-divider"></div><a class="dropdown-item" href="#">
-                <svg class="icon me-2">
-                  <use xlink:href="vendors/@coreui/icons/svg/free.svg#cil-lock-locked"></use>
-                </svg> Lock Account</a><a class="dropdown-item" href="#">
-                <svg class="icon me-2">
-                  <use xlink:href="vendors/@coreui/icons/svg/free.svg#cil-account-logout"></use>
-                </svg> Logout</a>
+                <i class="icon me-2 cil-lock-locked"></i> Lock Account</a><a class="dropdown-item" href="#">
+                <i class="icon me-2 cil-account-logout"></i> Logout</a>
             </div>
             </div>
           </li>
           </li>
         </ul>
         </ul>
       </div>
       </div>
+      <div class="container-fluid px-6">
+        <img src="/static/assets/images/Reisacher.png">
+        <h2>Forderungsmanagement</h2>
+      </div>
       <div class="container-fluid px-6">
       <div class="container-fluid px-6">
         {% block content %}{% endblock %}
         {% block content %}{% endblock %}
       </div>
       </div>

+ 55 - 0
templates/base/select.html

@@ -0,0 +1,55 @@
+{% extends "base/base.html" %}
+{% block content %}
+
+<br/>
+<br/>
+<br/>
+
+<div class="row row-cols-1 row-cols-md-4 g-4">
+  <div class="col">
+    <div class="card">
+      <img src="/static/assets/images/auth/forderung.jpg" class="card-img-top" alt="Forderungen">
+
+      <div class="card-body">
+        <h5 class="card-title">Forderungen</h5>
+        <p class="card-text">Alle offenen Posten im Überblick</p>
+        <a href="/app/forderungen/liste" class="btn btn-secondary">Öffnen</a>
+      </div>
+    </div>
+  </div>
+  <div class="col">
+    <div class="card">
+      <img src="/static/assets/images/auth/werkstatt.jpg" class="card-img-top" alt="Offene Aufträge">
+
+      <div class="card-body">
+        <h5 class="card-title">Offene Aufträge</h5>
+        <p class="card-text">Warum geht es nicht weiter?</p>
+        <a href="/app/forderungen/liste" class="btn btn-secondary">Öffnen</a>
+      </div>
+    </div>
+  </div>
+  <div class="col">
+    <div class="card">
+      <img src="/static/assets/images/auth/auftragseingang.jpg" class="card-img-top" alt="Fahrzeug-Auftragseingang">
+
+      <div class="card-body">
+        <h5 class="card-title">Fahrzeug-Auftragseingang</h5>
+        <p class="card-text">Mein Baby heißt WBABT31060...</p>
+        <a href="/app/forderungen/liste" class="btn btn-secondary">Öffnen</a>
+      </div>
+    </div>
+  </div>
+  <div class="col">
+    <div class="card">
+      <img src="/static/assets/images/auth/planung.jpg" class="card-img-top" alt="Planung">
+
+      <div class="card-body">
+        <h5 class="card-title">Planung</h5>
+        <p class="card-text">Höher, schneller, weiter!</p>
+        <a href="/app/forderungen/liste" class="btn btn-secondary">Öffnen</a>
+      </div>
+    </div>
+  </div>
+</div>
+
+{% endblock %}

+ 28 - 7
templates/forderungen/details.html

@@ -1,8 +1,7 @@
 {% extends "base/base.html" %}
 {% extends "base/base.html" %}
 {% block content %}
 {% block content %}
 
 
-
-<h2>Kommentare</h2>
+<h3>Kommentare</h3>
 
 
 <table class="table table-striped table-bordered">
 <table class="table table-striped table-bordered">
   <thead>
   <thead>
@@ -30,7 +29,26 @@
 </table>
 </table>
 
 
 
 
-<h2>Eingabemaske</h2>
+<h3>Dateien</h3>
+
+<table class="table table-striped table-bordered">
+  <thead>
+    <tr>
+        <th>Datum</th>
+        <th>Dateiname</th>
+    </tr>
+  </thead>
+  <tbody>
+    {% for row in files %}
+    <tr>
+      <td></td>
+      <td>{{ row }}</td>
+    </tr>
+    {% endfor %}
+  </tbody>
+</table>
+
+<h3>Eingabemaske</h3>
 
 
 <form class="row g-3">
 <form class="row g-3">
   <div class="col-md-6">
   <div class="col-md-6">
@@ -73,12 +91,15 @@
     </div>
     </div>
   </div>
   </div>
   <div class="col-12">
   <div class="col-12">
-    <button type="submit" class="btn btn-primary">Sign in</button>
+    <a class="btn btn-secondary" href="/app/forderungen/export/{{forderung_kopf[0].Client_DB}}_{{forderung_kopf[0].Document_No}}">Mahnung erstellen</a>
   </div>
   </div>
 </form>
 </form>
 
 
 
 
-<h2>Forderung Details</h2>
+
+
+
+<h3>Forderung Details</h3>
 
 
 <table class="table table-striped table-bordered">
 <table class="table table-striped table-bordered">
   <tbody>
   <tbody>
@@ -95,7 +116,7 @@
 </table>
 </table>
 
 
 
 
-<h2>Mahnungen</h2>
+<h3>Mahnungen</h3>
 
 
 <table class="table table-striped table-bordered">
 <table class="table table-striped table-bordered">
   <thead>
   <thead>
@@ -127,7 +148,7 @@
 
 
 
 
 
 
-<h2>Auftragspositionen</h2>
+<h3>Auftragspositionen</h3>
 
 
 <table class="table table-striped table-bordered">
 <table class="table table-striped table-bordered">
   <thead>
   <thead>

+ 68 - 34
templates/forderungen/liste.html

@@ -1,41 +1,50 @@
 {% extends "base/base.html" %}
 {% extends "base/base.html" %}
 {% block content %}
 {% block content %}
 <div class="d-flex mb-3">
 <div class="d-flex mb-3">
-  <a class="btn btn-secondary me-2" href="/export/csv">Export CSV</a>
   <a class="btn btn-secondary" href="/export/xlsx">Export XLSX</a>
   <a class="btn btn-secondary" href="/export/xlsx">Export XLSX</a>
 </div>
 </div>
 
 
-<form class="row g-3">
+<form class="row g-3" id="liste-filter"
+      hx-get=""
+      hx-params="*"
+      hx-trigger="change"
+      hx-push-url="true" 
+      hx-swap="innerHTML" 
+      hx-target="body">
   <div class="col-md-2">
   <div class="col-md-2">
     <label for="Hauptbetrieb" class="form-label">Hauptbetrieb</label>
     <label for="Hauptbetrieb" class="form-label">Hauptbetrieb</label>
-    <select id="Hauptbetrieb" class="form-select">
-        <option name="">-</option>
+    <select id="Hauptbetrieb" name="Hauptbetrieb" class="form-select">
+        <option value="">-</option>
       {% for key, value in filter.Hauptbetrieb.items() %}
       {% for key, value in filter.Hauptbetrieb.items() %}
-        <option name="{{ key }}">{{ value }}</option>
+        <option value="{{ key }}">{{ value }}</option>
       {% endfor %}
       {% endfor %}
     </select>
     </select>
   </div>
   </div>
   <div class="col-md-3">
   <div class="col-md-3">
     <label for="Standort" class="form-label">Standort</label>
     <label for="Standort" class="form-label">Standort</label>
-    <select id="Standort" class="form-select">
-        <option name="">-</option>
+    <select id="Standort" name="Standort" class="form-select">
+        <option value="">-</option>
       {% for key, value in filter.Standort.items() %}
       {% for key, value in filter.Standort.items() %}
-        <option name="{{ key }}">{{ value }}</option>
+        <option value="{{ key }}">{{ value }}</option>
       {% endfor %}
       {% endfor %}
     </select>
     </select>
   </div>
   </div>
   <div class="col-md-3">
   <div class="col-md-3">
     <label for="Bereich" class="form-label">Bereich</label>
     <label for="Bereich" class="form-label">Bereich</label>
-    <select id="Bereich" class="form-select">
-        <option name="">-</option>
+    <select id="Bereich" name="Bereich" class="form-select">
+        <option value="">-</option>
     </select>
     </select>
   </div>
   </div>
   <div class="col-md-4">
   <div class="col-md-4">
     <label for="Verursacher" class="form-label">Verursacher</label>
     <label for="Verursacher" class="form-label">Verursacher</label>
-    <select id="Verursacher" class="form-select">
-        <option name="">-</option>
+    <select id="Verursacher" name="Verursacher" class="form-select">
+        <option value="">-</option>
       {% for key, value in filter.Verursacher.items() %}
       {% for key, value in filter.Verursacher.items() %}
-        <option name="{{ key }}">{{ value }}</option>
+        {% if key == defaults.Verursacher %}
+        <option value="{{ key }}" selected>{{ value }}</option>
+        {% else %}
+        <option value="{{ key }}">{{ value }}</option>
+        {% endif %}
       {% endfor %}
       {% endfor %}
     </select>
     </select>
   </div>
   </div>
@@ -43,22 +52,26 @@
 
 
   <div class="col-md-3">
   <div class="col-md-3">
     <label for="Rechnungsnummer" class="form-label">Rechnungsnummer</label>
     <label for="Rechnungsnummer" class="form-label">Rechnungsnummer</label>
-    <input type="email" class="form-control" id="Rechnungsnummer">
+    <input type="email" class="form-control" id="Rechnungsnummer" name="Rechnungsnummer">
   </div>
   </div>
   <div class="col-md-2">
   <div class="col-md-2">
     <label for="RechnungsdatumVon" class="form-label">Rechnungsdatum von</label>
     <label for="RechnungsdatumVon" class="form-label">Rechnungsdatum von</label>
-    <input type="date" class="form-control" id="RechnungsdatumVon">
+    <input type="date" class="form-control" id="RechnungsdatumVon" name="RechnungsdatumVon">
   </div>
   </div>
   <div class="col-md-2">
   <div class="col-md-2">
     <label for="RechnungsdatumBis" class="form-label">Rechnungsdatum bis</label>
     <label for="RechnungsdatumBis" class="form-label">Rechnungsdatum bis</label>
-    <input type="date" class="form-control" id="RechnungsdatumBis">
+    <input type="date" class="form-control" id="RechnungsdatumBis" name="RechnungsdatumBis">
   </div>
   </div>
   <div class="col-md-5">
   <div class="col-md-5">
     <label for="Kunde" class="form-label">Kunde</label>
     <label for="Kunde" class="form-label">Kunde</label>
-    <select id="Kunde" class="form-select">
-        <option name="">-</option>
+    <select id="Kunde" name="Kunde" class="form-select">
+        <option value="">-</option>
       {% for key, value in filter.Kunde.items() %}
       {% for key, value in filter.Kunde.items() %}
-        <option name="{{ key }}">{{ value }}</option>
+        {% if key == defaults.Kunde %}
+        <option value="{{ key }}" selected>{{ value }}</option>
+        {% else %}
+        <option value="{{ key }}">{{ value }}</option>
+        {% endif %}
       {% endfor %}
       {% endfor %}
     </select>
     </select>
   </div>
   </div>
@@ -66,37 +79,41 @@
 
 
   <div class="col-md-2">
   <div class="col-md-2">
     <label for="WiedervorlageVon" class="form-label">Wiedervorlage von</label>
     <label for="WiedervorlageVon" class="form-label">Wiedervorlage von</label>
-    <input type="date" class="form-control" id="WiedervorlageVon">
+    <input type="date" class="form-control" id="WiedervorlageVon" name="WiedervorlageVon">
   </div>
   </div>
   <div class="col-md-2">
   <div class="col-md-2">
     <label for="WiedervorlageBis" class="form-label">Wiedervorlage bis</label>
     <label for="WiedervorlageBis" class="form-label">Wiedervorlage bis</label>
-    <input type="date" class="form-control" id="WiedervorlageBis">
+    <input type="date" class="form-control" id="WiedervorlageBis" name="WiedervorlageBis">
   </div>
   </div>
 
 
   <div class="col-md-4">
   <div class="col-md-4">
     <label for="Fahrzeug" class="form-label">Fahrzeug</label>
     <label for="Fahrzeug" class="form-label">Fahrzeug</label>
-    <select id="Fahrzeug" class="form-select">
-        <option name="">-</option>
+    <select id="Fahrzeug" name="Fahrzeug" class="form-select">
+        <option value="">-</option>
       {% for key, value in filter.Fahrzeug.items() %}
       {% for key, value in filter.Fahrzeug.items() %}
-        <option name="{{ key }}">{{ value }}</option>
+        <option value="{{ key }}">{{ value }}</option>
       {% endfor %}
       {% endfor %}
     </select>
     </select>
   </div>
   </div>
   <div class="col-md-2">
   <div class="col-md-2">
     <label for="Staffel" class="form-label">Staffel</label>
     <label for="Staffel" class="form-label">Staffel</label>
-    <select id="Staffel" class="form-select">
-        <option name="">-</option>
+    <select id="Staffel" name="Staffel" class="form-select">
+        <option value="">-</option>
       {% for key, value in filter.Staffel.items() %}
       {% for key, value in filter.Staffel.items() %}
-        <option name="{{ key }}">{{ value }}</option>
+        <option value="{{ key }}">{{ value }}</option>
       {% endfor %}
       {% endfor %}
     </select>
     </select>
   </div>
   </div>
   <div class="col-md-2">
   <div class="col-md-2">
     <label for="Mahnstufe" class="form-label">Mahnstufe</label>
     <label for="Mahnstufe" class="form-label">Mahnstufe</label>
-    <select id="Mahnstufe" class="form-select">
-        <option name="">-</option>
+    <select id="Mahnstufe" name="Mahnstufe" class="form-select">
+        <option value="">-</option>
       {% for key, value in filter.Mahnstufe.items() %}
       {% for key, value in filter.Mahnstufe.items() %}
-        <option name="{{ key }}">{{ value }}</option>
+        {% if value == defaults[key] %}
+        <option value="{{ key }}" selected>{{ value }}</option>
+        {% else %}
+        <option value="{{ key }}">{{ value }}</option>
+        {% endif %}
       {% endfor %}
       {% endfor %}
     </select>
     </select>
   </div>
   </div>
@@ -110,7 +127,7 @@
   </div>
   </div>
 </form>
 </form>
 
 
-
+<div  id="liste-content">
 <table class="table table-striped table-bordered">
 <table class="table table-striped table-bordered">
   <thead>
   <thead>
     <tr>
     <tr>
@@ -131,11 +148,27 @@
   <tbody>
   <tbody>
     {% for row in forderungen_liste %}
     {% for row in forderungen_liste %}
     <tr>
     <tr>
-      <td><a href="/forderungen/details/{{ row.Client_DB }}_{{ row.Document_No }}" class="btn btn-sm btn-primary"><i class="icon cil-pencil"></i></a></td>
+      <td>
+        <a href="/app/forderungen/details/{{ row.Client_DB }}_{{ row.Document_No }}" class="btn btn-sm btn-primary"><i class="icon cil-pencil"></i></a>
+      </td>
       <td>{{ row.Standort_Name }}</td>
       <td>{{ row.Standort_Name }}</td>
-      <td>{{ row.Kunde }}</td>
+      <td>
+        <a href="/app/forderungen/liste?Kunde={{ row.Kunde|urlencode }}">{{ row.Kunde }}</a>
+        {% if row.Kunde.startswith("K") %}
+        <a href="mailto:dummy@xyz.de?subject={{ row.Document_No }}" class="btn btn-sm btn-outline-secondary">
+            <i class="cil-at"></i>
+        </a>
+        {% endif %}
+      </td>
       <td>{{ row.Bereich }}</td>
       <td>{{ row.Bereich }}</td>
-      <td>{{ row.Verursacher }}</td>
+      <td>
+        <a href="/app/forderungen/liste?Verursacher={{ row.Verursacher|urlencode }}">{{ row.Verursacher }}</a>
+        {% if row.Verursacher == 'N.N.' %}
+        <a class="btn btn-sm btn-outline-secondary">
+            <i class="cil-user-follow"></i>
+        </a>
+        {% endif %}
+      </td>
       <td>{{ row.Document_No }}</td>
       <td>{{ row.Document_No }}</td>
       <td>{{ row.Invoice_Date|date_format }}</td>
       <td>{{ row.Invoice_Date|date_format }}</td>
       <td class="text-end">{{ row.Tage }}</td>
       <td class="text-end">{{ row.Tage }}</td>
@@ -147,4 +180,5 @@
     {% endfor %}
     {% endfor %}
   </tbody>
   </tbody>
 </table>
 </table>
+</div>
 {% endblock %}
 {% endblock %}

+ 1 - 0
templates/forderungen/queries/forderungen_liste.sql

@@ -29,6 +29,7 @@ SELECT [T1].[Client_DB]
      , T3.[Kommentar_Abteilung] 
      , T3.[Kommentar_Abteilung] 
 		 , T3.[Wiedervorlage]
 		 , T3.[Wiedervorlage]
 		 , T3.[Begründung]
 		 , T3.[Begründung]
+     , iif([T1].[Kunde] like 'k%', 'kunde@xyz.de', '') as Kunde_Email
 
 
 FROM [dbo].[Forderungen] T1
 FROM [dbo].[Forderungen] T1
 INNER JOIN [dbo].[Benutzer_Rechte] T2 ON (T2.Benutzer_ID = '{{ BenutzerSelect.selectedOptionValue }}' OR T2.Benutzer_ID = '')
 INNER JOIN [dbo].[Benutzer_Rechte] T2 ON (T2.Benutzer_ID = '{{ BenutzerSelect.selectedOptionValue }}' OR T2.Benutzer_ID = '')