fix: confirm deletes and restore recreated planning items

This commit is contained in:
2026-04-21 23:43:20 +02:00
parent 5b752ab7c4
commit 26bfa7fb64
4 changed files with 183 additions and 15 deletions
+104 -11
View File
@@ -681,10 +681,24 @@ def create_category(label: str):
flash("Bitte einen Bereich für die Kategorie wählen.", "danger")
return _dialog_redirect(month.label, request.form.get("return_dialog") or None)
account_id = account.id
existing = Category.query.filter_by(account_id=account_id, slug=slugify(name)).first()
slug = slugify(name)
existing = Category.query.filter_by(account_id=account_id, slug=slug).first()
if existing is not None:
flash("Kategorie existiert bereits.", "info")
return redirect(url_for("planning.detail", label=label))
if existing.is_active:
flash("Kategorie existiert bereits.", "info")
return redirect(url_for("planning.detail", label=label))
existing.name = name
existing.slug = slug
existing.description = request.form.get("description", "").strip() or None
existing.community_account_id = (
int(request.form["community_account_id"])
if account.slug == "gemeinschaftskonto" and request.form.get("community_account_id")
else None
)
existing.is_active = True
db.session.commit()
flash("Kategorie wiederhergestellt.", "success")
return _dialog_redirect(month.label, _category_dialog_id(existing))
last_sort = (
db.session.scalar(
select(Category.sort_order)
@@ -702,7 +716,7 @@ def create_category(label: str):
else None
),
name=name,
slug=slugify(name),
slug=slug,
is_active=True,
sort_order=last_sort + 1,
)
@@ -747,7 +761,7 @@ def create_entry(label: str):
category_id = request.form.get("category_id")
category = None
if category_id:
category = Category.query.get_or_404(int(category_id))
category = Category.query.get_or_404(int(category_id))
elif category_name and account_id:
category = Category.query.filter_by(
account_id=account_id,
@@ -772,14 +786,82 @@ def create_entry(label: str):
)
db.session.add(category)
db.session.flush()
elif not category.is_active:
category.is_active = True
db.session.flush()
if category is None:
flash("Bitte Konto und Kategorie angeben.", "danger")
return redirect(url_for("planning.detail", label=label))
slug = slugify(request.form.get("slug", "") or name)
existing = Entry.query.filter_by(category_id=category.id, slug=slug).first()
if existing is not None:
flash("Eintrag existiert bereits.", "info")
return redirect(url_for("planning.detail", label=label))
if existing.is_active:
flash("Eintrag existiert bereits.", "info")
return redirect(url_for("planning.detail", label=label))
existing.name = name
existing.slug = slug
existing.description = request.form.get("description", "").strip() or None
existing.default_amount = to_decimal(request.form.get("default_amount", "0"))
existing.amount_type = request.form.get("amount_type", "fixed")
existing.benefit_scope = request.form.get("benefit_scope", "all-users")
existing.is_allocation_target = request.form.get("is_allocation_target") == "on"
existing.is_active = True
entry = existing
db.session.flush()
months = Month.query.order_by(Month.year.asc(), Month.month.asc()).all()
current_note = request.form.get("note", "").strip() or None
current_amount = _resolve_monthly_amount(request.form)
existing_values = {item.month_id: item for item in entry.monthly_values}
for target_month in months:
value = existing_values.get(target_month.id)
if value is None:
db.session.add(
MonthlyEntryValue(
month_id=target_month.id,
entry_id=entry.id,
planned_amount=current_amount if target_month.id == month.id else entry.default_amount,
note=current_note if target_month.id == month.id else None,
created_by=current_user.id,
updated_by=current_user.id,
)
)
elif target_month.id == month.id:
value.planned_amount = current_amount
value.note = current_note
value.updated_by = current_user.id
selected_participants = {
int(item) for item in request.form.getlist("participant_ids") if item.strip()
}
existing_rules = {rule.participant_id: rule for rule in entry.share_rules}
for participant_id, rule in list(existing_rules.items()):
if participant_id not in selected_participants:
db.session.delete(rule)
for participant_id in selected_participants:
rule = existing_rules.get(participant_id)
if rule is None:
db.session.add(
EntryShareRule(
entry_id=entry.id,
participant_id=participant_id,
share_type="equal",
)
)
else:
rule.share_type = "equal"
rule.share_value = None
current_app.extensions["saldo.month_service"].sync_distribution_allocation_from_entry(
month,
entry,
mark_manual=True,
)
db.session.commit()
current_app.extensions["saldo.month_service"].refresh_suggestions(
month, reason="Eintrag wurde wiederhergestellt"
)
db.session.commit()
flash("Eintrag wiederhergestellt.", "success")
return_dialog = request.form.get("return_dialog") or _category_dialog_id(category)
return _dialog_redirect(label, return_dialog)
last_sort = (
db.session.scalar(
select(Entry.sort_order)
@@ -872,10 +954,21 @@ def create_community_account(label: str):
if not name:
flash("Bitte einen Namen für das Gemeinschaftskonto angeben.", "danger")
return _dialog_redirect(label, "community-account-create-dialog")
existing = CommunityAccount.query.filter_by(slug=slugify(name)).first()
slug = slugify(name)
existing = CommunityAccount.query.filter_by(slug=slug).first()
if existing is not None:
flash("Gemeinschaftskonto existiert bereits.", "info")
return _dialog_redirect(label, "community-account-create-dialog")
if existing.is_active:
flash("Gemeinschaftskonto existiert bereits.", "info")
return _dialog_redirect(label, "community-account-create-dialog")
existing.name = name
existing.slug = slug
existing.account_type = "shared"
existing.linked_account_slug = None
existing.description = request.form.get("description", "").strip() or None
existing.is_active = True
db.session.commit()
flash("Gemeinschaftskonto wiederhergestellt.", "success")
return _dialog_redirect(label)
last_sort = (
db.session.scalar(
select(CommunityAccount.sort_order)
@@ -887,7 +980,7 @@ def create_community_account(label: str):
)
community_account = CommunityAccount(
name=name,
slug=slugify(name),
slug=slug,
account_type="shared",
description=request.form.get("description", "").strip() or None,
sort_order=last_sort + 1,