Files
gaehsnitz/gaehsnitz/management/commands/seed_drinks_2026.py
T
flo 2056d5bbc7 Add staff dashboard, payment flow, seed extra 2026 expenses
Self-service /suff/pay/ page lets users record their own payments
(cash/PayPal/bank/other) against their tab. Open balance is shown on
/suff/me/ alongside total and paid amount, with a Bezahlen button when
something is owed.

Staff-only /suff/dashboard/ replaces the drink_stats / total_balance /
user_stats CLI commands with a mobile-friendly festival view: overall
refinancing progress bar (Spenden vs. Ausgaben with Bilanz), drinks
refinancing bar (sales revenue vs. purchase cost with profit), per-drink
sold/total/balance, open balances per user, and fun facts (top
spender, top drink, busiest day, and top user per festival day).
Linked from /suff/me/ when the logged-in user is staff.

seed_drinks_2026 also creates the non-drink Payments we already know
about (toilets, drinks/equipment down payment, band fees per stage day),
idempotently keyed on (purpose, date).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 22:18:57 +02:00

65 lines
2.4 KiB
Python

from datetime import date
from django.core.management import BaseCommand
from django.db import transaction
from gaehsnitz.models import Drink, Payment
PAYMENTS = [
# purpose, date, amount
("Toiletten", date(2026, 5, 6), 210.01),
("Anzahlung Getränke+Kühlschrank+Bänke", date(2026, 5, 18), 400.00),
("Band: Six Good Years", date(2026, 6, 12), 150.00),
("Band: Melo-Komplott", date(2026, 6, 12), 100.00),
("Band: Mörtel", date(2026, 6, 12), 150.00),
("Band: Kotpiloten", date(2026, 6, 13), 150.00),
("Band: Knast", date(2026, 6, 13), 150.00),
("Band: Quast", date(2026, 6, 13), 300.00),
]
DRINKS = [
# name, crates, btl/crate, size, price/crate, deposit/crate, sale/btl
("Sterni", 12, 20, 0.5, 10.99, 3.10, 2.00),
("Krosti", 5, 20, 0.5, 16.49, 3.10, 2.50),
("Buddi", 5, 20, 0.5, 20.99, 3.10, 2.50),
("Helles", 5, 20, 0.5, 15.99, 4.50, 2.50),
("Radler", 2, 20, 0.5, 14.99, 3.10, 2.50),
("Lübzer 0,0", 1, 20, 0.5, 17.99, 3.10, 2.50),
("Freiberger 0,0", 4, 20, 0.5, 15.49, 3.10, 2.50),
("Mate", 2, 20, 0.5, 17.49, 4.50, 2.50),
("Vita Cola", 2, 12, 1.0, 10.99, 3.30, 2.50),
("Spezi", 2, 20, 0.5, 17.99, 3.10, 2.50),
("Wasser", 10, 12, 1.0, 5.99, 3.30, 1.50),
]
class Command(BaseCommand):
help = "Seed Drink rows for the 2026 festival from the supplier invoice."
@transaction.atomic
def handle(self, *args, **options):
for purpose, day, amount in PAYMENTS:
obj, created = Payment.objects.update_or_create(
purpose=purpose,
date=day,
defaults={"amount": amount},
)
self.stdout.write(f"{'created' if created else 'updated'}: {obj.purpose} ({obj.date})")
for name, crates, btl, size, price, deposit, sale in DRINKS:
obj, created = Drink.objects.update_or_create(
name=name,
year=2026,
defaults={
"crates_ordered": crates,
"crates_purchased": crates,
"crates_returned": 0,
"purchase_price_per_crate": price,
"deposit_per_crate": deposit,
"bottles_per_crate": btl,
"bottle_size": size,
"sale_price_per_bottle": sale,
},
)
self.stdout.write(f"{'created' if created else 'updated'}: {obj.name}")