Compare commits
2 Commits
16f26691af
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 3dcbfecbe4 | |||
| 470044c9c9 |
@@ -605,6 +605,9 @@ function render(items) {
|
|||||||
// Sale-Badge anzeigen
|
// Sale-Badge anzeigen
|
||||||
const saleBadge = item.sale ? '<div class="sale-badge">SALE 🔥</div>' : '';
|
const saleBadge = item.sale ? '<div class="sale-badge">SALE 🔥</div>' : '';
|
||||||
|
|
||||||
|
// Info-Text (nur wenn vorhanden)
|
||||||
|
const infoText = item.info ? `<div class="card-info" style="margin-top: 8px; padding: 8px; background: rgba(243, 213, 42, 0.1); border-left: 3px solid var(--accent); border-radius: 4px; font-size: 12px; line-height: 1.4; color: var(--text);">ℹ️ ${item.info}</div>` : '';
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="card-tile">
|
<div class="card-tile">
|
||||||
${saleBadge}
|
${saleBadge}
|
||||||
@@ -615,6 +618,7 @@ function render(items) {
|
|||||||
<div class="card-title">${item.artikel}</div>
|
<div class="card-title">${item.artikel}</div>
|
||||||
<div class="card-price">${priceText}</div>
|
<div class="card-price">${priceText}</div>
|
||||||
<div class="card-sub">${item.rows.length} Größen</div>
|
<div class="card-sub">${item.rows.length} Größen</div>
|
||||||
|
${infoText}
|
||||||
${stockBadge}
|
${stockBadge}
|
||||||
</div>
|
</div>
|
||||||
<div class="card-actions">
|
<div class="card-actions">
|
||||||
@@ -692,7 +696,9 @@ document.addEventListener("click", (e) => {
|
|||||||
media.innerHTML = img ? `<img src="${img}" alt="${artikel}">` : "";
|
media.innerHTML = img ? `<img src="${img}" alt="${artikel}">` : "";
|
||||||
document.getElementById("detailTitle").textContent = artikel;
|
document.getElementById("detailTitle").textContent = artikel;
|
||||||
document.getElementById("detailPrice").textContent = detailBtn.dataset.preis || "Preis auf Anfrage";
|
document.getElementById("detailPrice").textContent = detailBtn.dataset.preis || "Preis auf Anfrage";
|
||||||
document.getElementById("detailSizes").textContent = `${item.rows.length} Größen`;
|
const sizesText = `${item.rows.length} Größen`;
|
||||||
|
const infoText = item.info ? ` · ℹ️ ${item.info}` : '';
|
||||||
|
document.getElementById("detailSizes").textContent = sizesText + infoText;
|
||||||
const list = item.rows.map(r => {
|
const list = item.rows.map(r => {
|
||||||
const stock = Number(r.gezaehlt) || 0;
|
const stock = Number(r.gezaehlt) || 0;
|
||||||
let stockInfo = '';
|
let stockInfo = '';
|
||||||
|
|||||||
43
wawi/app.py
43
wawi/app.py
@@ -167,6 +167,7 @@ def init_db() -> None:
|
|||||||
ensure_price_column(db)
|
ensure_price_column(db)
|
||||||
ensure_image_column(db)
|
ensure_image_column(db)
|
||||||
ensure_sale_column(db)
|
ensure_sale_column(db)
|
||||||
|
ensure_info_column(db)
|
||||||
ensure_orders_columns(db)
|
ensure_orders_columns(db)
|
||||||
ensure_payment_columns(db)
|
ensure_payment_columns(db)
|
||||||
ensure_indexes(db)
|
ensure_indexes(db)
|
||||||
@@ -201,6 +202,16 @@ def ensure_sale_column(db: sqlite3.Connection) -> None:
|
|||||||
logger.info("Sale-Spalte für items erstellt")
|
logger.info("Sale-Spalte für items erstellt")
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_info_column(db: sqlite3.Connection) -> None:
|
||||||
|
"""Fügt info-Spalte für zusätzliche Artikelinformationen hinzu."""
|
||||||
|
cols = db.execute("PRAGMA table_info(items)").fetchall()
|
||||||
|
if any(c["name"] == "info" for c in cols):
|
||||||
|
return
|
||||||
|
db.execute("ALTER TABLE items ADD COLUMN info TEXT")
|
||||||
|
db.commit()
|
||||||
|
logger.info("Info-Spalte für items erstellt")
|
||||||
|
|
||||||
|
|
||||||
def ensure_orders_columns(db: sqlite3.Connection) -> None:
|
def ensure_orders_columns(db: sqlite3.Connection) -> None:
|
||||||
"""Sorgt für alle nachträglich eingeführten Orders‑Spalten."""
|
"""Sorgt für alle nachträglich eingeführten Orders‑Spalten."""
|
||||||
cols = db.execute("PRAGMA table_info(orders)").fetchall()
|
cols = db.execute("PRAGMA table_info(orders)").fetchall()
|
||||||
@@ -475,6 +486,7 @@ def new_item():
|
|||||||
if uploaded:
|
if uploaded:
|
||||||
bild_url = uploaded
|
bild_url = uploaded
|
||||||
sale = 1 if request.form.get("sale") else 0
|
sale = 1 if request.form.get("sale") else 0
|
||||||
|
info = (request.form.get("info") or "").strip() or None
|
||||||
soll = int(request.form.get("soll") or 0)
|
soll = int(request.form.get("soll") or 0)
|
||||||
gezaehlt = int(request.form.get("gezaehlt") or 0)
|
gezaehlt = int(request.form.get("gezaehlt") or 0)
|
||||||
verkaeufe = int(request.form.get("verkaeufe") or 0)
|
verkaeufe = int(request.form.get("verkaeufe") or 0)
|
||||||
@@ -483,12 +495,12 @@ def new_item():
|
|||||||
db = get_db()
|
db = get_db()
|
||||||
db.execute(
|
db.execute(
|
||||||
"""
|
"""
|
||||||
INSERT INTO items (artikel, groesse, preis, bild_url, sale, soll, gezaehlt, verkaeufe, created_at, updated_at)
|
INSERT INTO items (artikel, groesse, preis, bild_url, sale, info, soll, gezaehlt, verkaeufe, created_at, updated_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
""",
|
""",
|
||||||
(artikel, groesse, preis, bild_url, sale, soll, gezaehlt, verkaeufe, now_iso(), now_iso()),
|
(artikel, groesse, preis, bild_url, sale, info, soll, gezaehlt, verkaeufe, now_iso(), now_iso()),
|
||||||
)
|
)
|
||||||
db.execute("UPDATE items SET preis = ?, bild_url = ?, sale = ? WHERE artikel = ?", (preis, bild_url, sale, artikel))
|
db.execute("UPDATE items SET preis = ?, bild_url = ?, sale = ?, info = ? WHERE artikel = ?", (preis, bild_url, sale, info, artikel))
|
||||||
db.commit()
|
db.commit()
|
||||||
return redirect(url_for("bp.index"))
|
return redirect(url_for("bp.index"))
|
||||||
|
|
||||||
@@ -513,6 +525,7 @@ def edit_item(item_id: int):
|
|||||||
if uploaded:
|
if uploaded:
|
||||||
bild_url = uploaded
|
bild_url = uploaded
|
||||||
sale = 1 if request.form.get("sale") else 0
|
sale = 1 if request.form.get("sale") else 0
|
||||||
|
info = (request.form.get("info") or "").strip() or None
|
||||||
soll = int(request.form.get("soll") or 0)
|
soll = int(request.form.get("soll") or 0)
|
||||||
gezaehlt = int(request.form.get("gezaehlt") or 0)
|
gezaehlt = int(request.form.get("gezaehlt") or 0)
|
||||||
verkaeufe = int(request.form.get("verkaeufe") or 0)
|
verkaeufe = int(request.form.get("verkaeufe") or 0)
|
||||||
@@ -520,12 +533,12 @@ def edit_item(item_id: int):
|
|||||||
db.execute(
|
db.execute(
|
||||||
"""
|
"""
|
||||||
UPDATE items
|
UPDATE items
|
||||||
SET artikel = ?, groesse = ?, preis = ?, bild_url = ?, sale = ?, soll = ?, gezaehlt = ?, verkaeufe = ?, updated_at = ?
|
SET artikel = ?, groesse = ?, preis = ?, bild_url = ?, sale = ?, info = ?, soll = ?, gezaehlt = ?, verkaeufe = ?, updated_at = ?
|
||||||
WHERE id = ?
|
WHERE id = ?
|
||||||
""",
|
""",
|
||||||
(artikel, groesse, preis, bild_url, sale, soll, gezaehlt, verkaeufe, now_iso(), item_id),
|
(artikel, groesse, preis, bild_url, sale, info, soll, gezaehlt, verkaeufe, now_iso(), item_id),
|
||||||
)
|
)
|
||||||
db.execute("UPDATE items SET preis = ?, bild_url = ?, sale = ? WHERE artikel = ?", (preis, bild_url, sale, artikel))
|
db.execute("UPDATE items SET preis = ?, bild_url = ?, sale = ?, info = ? WHERE artikel = ?", (preis, bild_url, sale, info, artikel))
|
||||||
db.commit()
|
db.commit()
|
||||||
return redirect(url_for("bp.index"))
|
return redirect(url_for("bp.index"))
|
||||||
|
|
||||||
@@ -719,7 +732,7 @@ def build_bestand() -> list[dict]:
|
|||||||
"""Aggregiert DB‑Zeilen in die Struktur der Live‑Bestand Ansicht."""
|
"""Aggregiert DB‑Zeilen in die Struktur der Live‑Bestand Ansicht."""
|
||||||
rows = get_db().execute(
|
rows = get_db().execute(
|
||||||
"""
|
"""
|
||||||
SELECT artikel, groesse, preis, bild_url, sale, soll, gezaehlt, verkaeufe
|
SELECT artikel, groesse, preis, bild_url, sale, info, soll, gezaehlt, verkaeufe
|
||||||
FROM items
|
FROM items
|
||||||
ORDER BY artikel, groesse
|
ORDER BY artikel, groesse
|
||||||
"""
|
"""
|
||||||
@@ -732,7 +745,7 @@ def build_bestand() -> list[dict]:
|
|||||||
continue
|
continue
|
||||||
item = data.setdefault(
|
item = data.setdefault(
|
||||||
artikel,
|
artikel,
|
||||||
{"artikel": artikel, "preis": 0, "bild_url": "", "sale": 0, "rows": [], "totals": {"soll": 0, "gezaehlt": 0, "abweichung": 0, "fehlbestand": 0, "verkaeufe": 0}},
|
{"artikel": artikel, "preis": 0, "bild_url": "", "sale": 0, "info": None, "rows": [], "totals": {"soll": 0, "gezaehlt": 0, "abweichung": 0, "fehlbestand": 0, "verkaeufe": 0}},
|
||||||
)
|
)
|
||||||
if not item["preis"]:
|
if not item["preis"]:
|
||||||
item["preis"] = float(r["preis"] or 0)
|
item["preis"] = float(r["preis"] or 0)
|
||||||
@@ -741,6 +754,9 @@ def build_bestand() -> list[dict]:
|
|||||||
# Sale-Status (1 wenn mindestens eine Größe sale=1 hat)
|
# Sale-Status (1 wenn mindestens eine Größe sale=1 hat)
|
||||||
if r["sale"]:
|
if r["sale"]:
|
||||||
item["sale"] = 1
|
item["sale"] = 1
|
||||||
|
# Info-Text (nur wenn vorhanden)
|
||||||
|
if r["info"] and not item["info"]:
|
||||||
|
item["info"] = (r["info"] or "").strip()
|
||||||
soll = int(r["soll"] or 0)
|
soll = int(r["soll"] or 0)
|
||||||
gezaehlt = int(r["gezaehlt"] or 0)
|
gezaehlt = int(r["gezaehlt"] or 0)
|
||||||
verkaeufe = int(r["verkaeufe"] or 0)
|
verkaeufe = int(r["verkaeufe"] or 0)
|
||||||
@@ -886,13 +902,8 @@ def order():
|
|||||||
db = get_db()
|
db = get_db()
|
||||||
cursor = db.execute(
|
cursor = db.execute(
|
||||||
"""
|
"""
|
||||||
<<<<<<< HEAD
|
|
||||||
INSERT INTO orders (name, handy, email, mannschaft, artikel, groesse, menge, notiz, created_at, done, completed_by, completed_at, canceled, canceled_by, canceled_at, payment_method, payment_status)
|
INSERT INTO orders (name, handy, email, mannschaft, artikel, groesse, menge, notiz, created_at, done, completed_by, completed_at, canceled, canceled_by, canceled_at, payment_method, payment_status)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 0, NULL, NULL, 0, NULL, NULL, ?, 'unpaid')
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 0, NULL, NULL, 0, NULL, NULL, ?, 'unpaid')
|
||||||
=======
|
|
||||||
INSERT INTO orders (name, handy, mannschaft, artikel, groesse, menge, notiz, created_at, done, completed_by, completed_at, canceled, canceled_by, canceled_at, payment_method, payment_status)
|
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 0, NULL, NULL, 0, NULL, NULL, ?, 'unpaid')
|
|
||||||
>>>>>>> origin/main
|
|
||||||
""",
|
""",
|
||||||
(
|
(
|
||||||
data.get("name"),
|
data.get("name"),
|
||||||
@@ -1031,11 +1042,7 @@ def orders():
|
|||||||
"""Bestellliste in der Verwaltung."""
|
"""Bestellliste in der Verwaltung."""
|
||||||
rows = get_db().execute(
|
rows = get_db().execute(
|
||||||
"""
|
"""
|
||||||
<<<<<<< HEAD
|
|
||||||
SELECT id, name, handy, email, mannschaft, artikel, groesse, menge, notiz, created_at, done, completed_by, completed_at, canceled, canceled_by, canceled_at, payment_method, payment_status, paid_at, paid_by
|
SELECT id, name, handy, email, mannschaft, artikel, groesse, menge, notiz, created_at, done, completed_by, completed_at, canceled, canceled_by, canceled_at, payment_method, payment_status, paid_at, paid_by
|
||||||
=======
|
|
||||||
SELECT id, name, handy, mannschaft, artikel, groesse, menge, notiz, created_at, done, completed_by, completed_at, canceled, canceled_by, canceled_at, payment_method, payment_status, paid_at, paid_by
|
|
||||||
>>>>>>> origin/main
|
|
||||||
FROM orders
|
FROM orders
|
||||||
ORDER BY id DESC
|
ORDER BY id DESC
|
||||||
LIMIT 500
|
LIMIT 500
|
||||||
|
|||||||
@@ -29,6 +29,10 @@
|
|||||||
<input type="checkbox" name="sale" value="1" {% if item and item.sale %}checked{% endif %} style="width: auto; height: 18px;" />
|
<input type="checkbox" name="sale" value="1" {% if item and item.sale %}checked{% endif %} style="width: auto; height: 18px;" />
|
||||||
<span style="color: var(--text);">Sale / Abverkauf 🔥</span>
|
<span style="color: var(--text);">Sale / Abverkauf 🔥</span>
|
||||||
</label>
|
</label>
|
||||||
|
<label style="grid-column: 1 / -1;">
|
||||||
|
Info-Text für Shop (optional)
|
||||||
|
<textarea name="info" rows="3" placeholder="z.B. Lieferzeit 2-3 Wochen, limitierte Auflage, etc.">{{ item.info if item and item.info else '' }}</textarea>
|
||||||
|
</label>
|
||||||
<label>
|
<label>
|
||||||
Soll
|
Soll
|
||||||
<input type="number" name="soll" min="0" value="{{ item.soll if item else 0 }}" />
|
<input type="number" name="soll" min="0" value="{{ item.soll if item else 0 }}" />
|
||||||
|
|||||||
Reference in New Issue
Block a user