Compare commits

1 Commits

Author SHA1 Message Date
flo bb41961bc0 Update dependency gunicorn to v24 2026-01-23 07:00:52 +00:00
26 changed files with 712 additions and 1297 deletions
-10
View File
@@ -1,10 +0,0 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
max_line_length = 120
trim_trailing_whitespace = true
+4 -6
View File
@@ -1,10 +1,8 @@
FROM python:3.14-alpine FROM python:3.14-alpine
ENV PYTHONUNBUFFERED=1 ENV PYTHONUNBUFFERED=1
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /usr/local/bin/ WORKDIR /code/
WORKDIR /app COPY requirements.txt .
COPY pyproject.toml . RUN pip install --upgrade pip && \
ENV VIRTUAL_ENV=/opt/venv pip install --no-cache-dir --requirement requirements.txt
RUN uv venv $VIRTUAL_ENV && uv pip install -r pyproject.toml
ENV PATH="/opt/venv/bin:$PATH"
COPY . . COPY . .
ENTRYPOINT ["./entrypoint.sh"] ENTRYPOINT ["./entrypoint.sh"]
+3 -2
View File
@@ -1,4 +1,5 @@
services: services:
db: db:
image: postgres:18-alpine image: postgres:18-alpine
init: true init: true
@@ -9,7 +10,7 @@ services:
expose: expose:
- "5432" - "5432"
volumes: volumes:
- ./volumes/db/postgresql:/var/lib/postgresql:rw - ./volumes/db/data:/var/lib/postgresql/data:rw
web: web:
build: build:
@@ -26,4 +27,4 @@ services:
ports: ports:
- "80:8000" - "80:8000"
volumes: volumes:
- .:/app - .:/code:rw
+28 -65
View File
@@ -20,18 +20,17 @@ class CustomUserAdmin(UserAdmin):
ordering = ("username",) ordering = ("username",)
list_filter = [] list_filter = []
fieldsets = ( fieldsets = (
( (None, {"fields": (
None,
{
"fields": (
"username", "username",
"password", "password",
)}),
("BALANCE", {"fields": (
"consumed_drinks_price",
)}),
) )
}, readonly_fields = (
), "consumed_drinks_price",
("BALANCE", {"fields": ("consumed_drinks_price",)}),
) )
readonly_fields = ("consumed_drinks_price",)
inlines = (ConsumptionInline,) inlines = (ConsumptionInline,)
def consumed_drinks_price(self, user: User): def consumed_drinks_price(self, user: User):
@@ -62,62 +61,36 @@ class PaymentAdmin(admin.ModelAdmin):
class DrinkAdmin(admin.ModelAdmin): class DrinkAdmin(admin.ModelAdmin):
list_display = ("name", "purchase_price_per_crate", "crates_purchased", "purchase_price_total") list_display = ("name", "purchase_price_per_crate", "crates_purchased", "purchase_price_total")
fieldsets = ( fieldsets = (
(None, {"fields": ("name",)}), (None, {"fields": (
( "name",
"crates", )}),
{ ("crates", {"fields": (
"fields": (
"crates_ordered", "crates_ordered",
"crates_purchased", "crates_purchased",
"crates_returned", "crates_returned",
) )}),
}, ("bottles", {"fields": (
),
(
"bottles",
{
"fields": (
"bottles_per_crate", "bottles_per_crate",
"bottles_total", "bottles_total",
"bottles_returned", "bottles_returned",
) )}),
}, ("amount", {"fields": (
),
(
"amount",
{
"fields": (
"bottle_size", "bottle_size",
"amount_per_crate", "amount_per_crate",
"amount_total", "amount_total",
) )}),
}, ("purchase", {"fields": (
),
(
"purchase",
{
"fields": (
"purchase_price_per_crate", "purchase_price_per_crate",
"purchase_price_per_bottle", "purchase_price_per_bottle",
"purchase_price_total", "purchase_price_total",
) )}),
}, ("deposit", {"fields": (
),
(
"deposit",
{
"fields": (
"deposit_per_crate", "deposit_per_crate",
"deposit_total", "deposit_total",
"deposit_refund", "deposit_refund",
"deposit_kept", "deposit_kept",
) )}),
}, ("sales", {"fields": (
),
(
"sales",
{
"fields": (
"sale_price_per_bottle", "sale_price_per_bottle",
"bottles_sold", "bottles_sold",
"sales_purchase_value", "sales_purchase_value",
@@ -125,25 +98,15 @@ class DrinkAdmin(admin.ModelAdmin):
"bottles_given_away", "bottles_given_away",
"giveaway_purchase_value", "giveaway_purchase_value",
"balance", "balance",
) )}),
},
),
) )
readonly_fields = ( readonly_fields = (
"bottles_total", "bottles_total", "bottles_returned",
"bottles_returned", "amount_per_crate", "amount_total",
"amount_per_crate", "purchase_price_per_bottle", "purchase_price_total",
"amount_total", "deposit_total", "deposit_refund", "deposit_kept",
"purchase_price_per_bottle", "bottles_sold", "sales_purchase_value", "sale_price_total",
"purchase_price_total", "bottles_given_away", "giveaway_purchase_value",
"deposit_total",
"deposit_refund",
"deposit_kept",
"bottles_sold",
"sales_purchase_value",
"sale_price_total",
"bottles_given_away",
"giveaway_purchase_value",
"balance", "balance",
) )
+17 -39
View File
@@ -46,14 +46,16 @@ def payback(user, day, month, amount, note):
def consumption(day: int, for_free: bool, drink_dict: Dict[User, List[Tuple[int, Drink]]]): def consumption(day: int, for_free: bool, drink_dict: Dict[User, List[Tuple[int, Drink]]]):
for user, drink_list in drink_dict.items(): for user, drink_list in drink_dict.items():
for amount, drink in drink_list: for amount, drink in drink_list:
Consumption.objects.create(user=user, drink=drink, amount=amount, day=day, for_free=for_free) Consumption.objects.create(
user=user, drink=drink, amount=amount, day=day, for_free=for_free)
class Command(BaseCommand): class Command(BaseCommand):
@transaction.atomic() @transaction.atomic()
def handle(self, *args, **options): def handle(self, *args, **options):
if any(model.objects.exists() for model in [Donation, Payment, Drink, Consumption]): if any(model.objects.exists() for model in [Donation, Payment, Drink, Consumption]):
raise CommandError("clear all donation, payment, drink and consumption objects before running this command") raise CommandError(
"clear all donation, payment, drink and consumption objects before running this command")
# --------------- PEOPLE --------------- # --------------- PEOPLE ---------------
@@ -222,10 +224,7 @@ class Command(BaseCommand):
# --------------- THURSDAY --------------- # --------------- THURSDAY ---------------
consumption( consumption(day=1, for_free=False, drink_dict={
day=1,
for_free=False,
drink_dict={
robert: [(2, mate), (2, radler), (1, wasser)], robert: [(2, mate), (2, radler), (1, wasser)],
thure: [(4, sterni), (1, krosti), (2, radler)], thure: [(4, sterni), (1, krosti), (2, radler)],
tobi: [(7, sterni), (2, krosti)], tobi: [(7, sterni), (2, krosti)],
@@ -238,22 +237,14 @@ class Command(BaseCommand):
lutz: [(1, sterni), (1, wasser)], lutz: [(1, sterni), (1, wasser)],
lasse: [(2, sterni), (1, wasser)], lasse: [(2, sterni), (1, wasser)],
domi: [(1, sterni), (1, radler)], domi: [(1, sterni), (1, radler)],
}, })
) consumption(day=1, for_free=True, drink_dict={
consumption(
day=1,
for_free=True,
drink_dict={
seth_family: [(1, krosti), (1, radler)], seth_family: [(1, krosti), (1, radler)],
}, })
)
# --------------- FRIDAY --------------- # --------------- FRIDAY ---------------
consumption( consumption(day=2, for_free=False, drink_dict={
day=2,
for_free=False,
drink_dict={
robert: [(2, mate), (1, radler)], robert: [(2, mate), (1, radler)],
thure: [(8, sterni), (2, krosti), (1, wasser)], thure: [(8, sterni), (2, krosti), (1, wasser)],
tobi: [(2, mate), (5, sterni), (5, krosti), (3, radler), (1, cola)], tobi: [(2, mate), (5, sterni), (5, krosti), (3, radler), (1, cola)],
@@ -266,29 +257,21 @@ class Command(BaseCommand):
peter: [(7, sterni), (1, krosti), (2, wasser)], peter: [(7, sterni), (1, krosti), (2, wasser)],
fiddi_melli: [(6, sterni), (3, radler), (1, wasser)], fiddi_melli: [(6, sterni), (3, radler), (1, wasser)],
suse: [(1, krosti), (1, radler)], suse: [(1, krosti), (1, radler)],
lilly_simon: [(1, mate), (7, sterni), (3, wasser)], lilly_simon: [(1, mate), (7, sterni), (3, wasser)]
}, })
)
consumption( consumption(day=2, for_free=True, drink_dict={
day=2,
for_free=True,
drink_dict={
seth_family: [(1, mate), (6, sterni), (3, wasser)], seth_family: [(1, mate), (6, sterni), (3, wasser)],
aimee: [(1, mate), (9, sterni), (3, wasser)], aimee: [(1, mate), (9, sterni), (3, wasser)],
lutz: [(1, mate), (9, sterni), (3, wasser)], lutz: [(1, mate), (9, sterni), (3, wasser)],
lasse: [(7, sterni), (1, wasser)], lasse: [(7, sterni), (1, wasser)],
domi: [(1, mate), (4, sterni), (1, wasser)], domi: [(1, mate), (4, sterni), (1, wasser)],
hans_welle: [(3, mate), (7, sterni), (7, krosti), (1, cola), (2, wasser)], hans_welle: [(3, mate), (7, sterni), (7, krosti), (1, cola), (2, wasser)],
}, })
)
# --------------- SATURDAY --------------- # --------------- SATURDAY ---------------
consumption( consumption(day=3, for_free=False, drink_dict={
day=3,
for_free=False,
drink_dict={
robert: [(4, mate), (1, cola), (4, wasser)], robert: [(4, mate), (1, cola), (4, wasser)],
tobi: [(9, sterni), (1, krosti), (2, radler), (1, cola)], tobi: [(9, sterni), (1, krosti), (2, radler), (1, cola)],
herald: [(2, mate), (2, radler), (3, wasser), (5, wein)], herald: [(2, mate), (2, radler), (3, wasser), (5, wein)],
@@ -307,21 +290,16 @@ class Command(BaseCommand):
kevin: [(1, mate), (1, radler)], kevin: [(1, mate), (1, radler)],
rebecca: [(1, radler)], rebecca: [(1, radler)],
resi_simon: [(8, sterni), (1, radler), (1, wasser)], resi_simon: [(8, sterni), (1, radler), (1, wasser)],
}, })
)
consumption( consumption(day=3, for_free=True, drink_dict={
day=3,
for_free=True,
drink_dict={
thure: [(1, mate), (4, sterni), (5, radler), (3, wasser)], thure: [(1, mate), (4, sterni), (5, radler), (3, wasser)],
seth_family: [(1, mate), (2, sterni), (12, krosti), (1, wasser)], seth_family: [(1, mate), (2, sterni), (12, krosti), (1, wasser)],
andrew: [(3, sterni), (2, krosti), (3, radler), (1, wasser)], andrew: [(3, sterni), (2, krosti), (3, radler), (1, wasser)],
robin: [(1, mate), (4, krosti), (2, radler)], robin: [(1, mate), (4, krosti), (2, radler)],
melokomplott: [(5, mate), (13, sterni), (1, krosti), (1, radler)], melokomplott: [(5, mate), (13, sterni), (1, krosti), (1, radler)],
residudes: [(2, mate), (1, sterni), (15, krosti), (7, radler), (1, wasser)], residudes: [(2, mate), (1, sterni), (15, krosti), (7, radler), (1, wasser)],
}, })
)
# --------------- ADMIN STUFF --------------- # --------------- ADMIN STUFF ---------------
+17 -35
View File
@@ -35,14 +35,16 @@ def payment(purpose, day, month, amount):
def consumption(day: int, for_free: bool, drink_dict: Dict[User, List[Tuple[int, Drink]]]): def consumption(day: int, for_free: bool, drink_dict: Dict[User, List[Tuple[int, Drink]]]):
for user, drink_list in drink_dict.items(): for user, drink_list in drink_dict.items():
for amount, drink in drink_list: for amount, drink in drink_list:
Consumption.objects.create(user=user, drink=drink, amount=amount, day=day, for_free=for_free) Consumption.objects.create(
user=user, drink=drink, amount=amount, day=day, for_free=for_free)
class Command(BaseCommand): class Command(BaseCommand):
@transaction.atomic() @transaction.atomic()
def handle(self, *args, **options): def handle(self, *args, **options):
if any(model.objects.exists() for model in [Donation, Payment, Drink, Consumption]): if any(model.objects.exists() for model in [Donation, Payment, Drink, Consumption]):
raise CommandError("clear all donation, payment, drink and consumption objects before running this command") raise CommandError(
"clear all donation, payment, drink and consumption objects before running this command")
# --------------- PEOPLE --------------- # --------------- PEOPLE ---------------
@@ -230,10 +232,7 @@ class Command(BaseCommand):
# --------------- THURSDAY --------------- # --------------- THURSDAY ---------------
consumption( consumption(day=1, for_free=False, drink_dict={
day=1,
for_free=False,
drink_dict={
enni: [(2, wasser), (9, sterni)], enni: [(2, wasser), (9, sterni)],
robert: [(2, wasser), (2, freiberger), (1, spezi), (2, mate)], robert: [(2, wasser), (2, freiberger), (1, spezi), (2, mate)],
josi: [(5, sterni), (1, radler)], josi: [(5, sterni), (1, radler)],
@@ -241,15 +240,11 @@ class Command(BaseCommand):
annemarie: [(1, wasser), (4, sterni), (1, radler)], annemarie: [(1, wasser), (4, sterni), (1, radler)],
sandra: [(1, wasser), (3, sterni), (1, spezi), (1, mate)], sandra: [(1, wasser), (3, sterni), (1, spezi), (1, mate)],
flo: [(2, wasser), (5, sterni), (1, mate), (1, helles)], flo: [(2, wasser), (5, sterni), (1, mate), (1, helles)],
}, })
)
# --------------- FRIDAY --------------- # --------------- FRIDAY ---------------
consumption( consumption(day=2, for_free=False, drink_dict={
day=2,
for_free=False,
drink_dict={
tobi: [(2, wasser), (9, sterni), (2, freiberger)], tobi: [(2, wasser), (9, sterni), (2, freiberger)],
annemarie: [(1, wasser), (5, sterni), (2, mate), (2, radler), (2, buddi), (3, sekt)], annemarie: [(1, wasser), (5, sterni), (2, mate), (2, radler), (2, buddi), (3, sekt)],
sandra: [(1, freiberger), (1, buddi), (1, spezi), (2, mate), (1, radler), (2, sekt)], sandra: [(1, freiberger), (1, buddi), (1, spezi), (2, mate), (1, radler), (2, sekt)],
@@ -272,28 +267,20 @@ class Command(BaseCommand):
dennis: [(1, sterni), (2, krosti)], dennis: [(1, sterni), (2, krosti)],
marvin: [(3, sterni), (1, krosti), (1, mate)], marvin: [(3, sterni), (1, krosti), (1, mate)],
simon: [(1, sterni)], simon: [(1, sterni)],
}, })
)
consumption( consumption(day=2, for_free=True, drink_dict={
day=2,
for_free=True,
drink_dict={
flo: [(2, wasser), (3, sterni), (1, freiberger), (3, helles)], flo: [(2, wasser), (3, sterni), (1, freiberger), (3, helles)],
casi: [(6, sterni)], casi: [(6, sterni)],
sepp: [(6, sterni)], sepp: [(6, sterni)],
ohli: [(4, sterni)], ohli: [(4, sterni)],
marius: [(1, radler)], marius: [(1, radler)],
anonym: [(10, sterni), (10, krosti), (2, radler), (4, helles), (1, sekt)], anonym: [(10, sterni), (10, krosti), (2, radler), (4, helles), (1, sekt)]
}, })
)
# --------------- SATURDAY --------------- # --------------- SATURDAY ---------------
consumption( consumption(day=3, for_free=False, drink_dict={
day=3,
for_free=False,
drink_dict={
herald: [(1, sterni), (2, freiberger), (2, radler), (1, buddi), (5, spezi), (2, wasser)], herald: [(1, sterni), (2, freiberger), (2, radler), (1, buddi), (5, spezi), (2, wasser)],
thure: [(6, sterni), (1, krosti), (1, radler), (2, spezi)], thure: [(6, sterni), (1, krosti), (1, radler), (2, spezi)],
sandra: [(6, sterni), (1, freiberger), (2, radler), (1, mate), (1, cola), (1, sekt)], sandra: [(6, sterni), (1, freiberger), (2, radler), (1, mate), (1, cola), (1, sekt)],
@@ -318,18 +305,13 @@ class Command(BaseCommand):
lilly: [(5, sterni), (1, mate)], lilly: [(5, sterni), (1, mate)],
andrea: [(1, buddi)], andrea: [(1, buddi)],
lena: [(1, sterni)], lena: [(1, sterni)],
anonym: [(2, helles), (3, sterni), (5, krosti), (2, radler), (1, cola), (2, sekt)], anonym: [(2, helles), (3, sterni), (5, krosti), (2, radler), (1, cola), (2, sekt)]
}, })
)
consumption( consumption(day=3, for_free=True, drink_dict={
day=3,
for_free=True,
drink_dict={
rockbert: [(8, krosti), (1, radler), (1, mate)], rockbert: [(8, krosti), (1, radler), (1, mate)],
anonym: [(8, sterni), (2, krosti), (2, mate), (1, cola)], anonym: [(8, sterni), (2, krosti), (2, mate), (1, cola)]
}, })
)
# --------------- ADMIN STUFF --------------- # --------------- ADMIN STUFF ---------------
+1 -1
View File
@@ -20,4 +20,4 @@ class Command(BaseCommand):
name = id_to_name[drink_dict["drink_id"]] name = id_to_name[drink_dict["drink_id"]]
amount = drink_dict["amount"] amount = drink_dict["amount"]
drink_list.append(f"{amount}x {name}") drink_list.append(f"{amount}x {name}")
print(f"{user.username.capitalize()}: {euro(to_pay)} ({', '.join(drink_list)})") print(f"{user.username.capitalize()}: {euro(to_pay)} ({", ".join(drink_list)})")
+56 -151
View File
@@ -10,189 +10,94 @@ import gaehsnitz.models
class Migration(migrations.Migration): class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
("auth", "0012_alter_user_first_name_max_length"), ('auth', '0012_alter_user_first_name_max_length'),
] ]
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name="User", name='User',
fields=[ fields=[
("id", models.SmallAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), ('id', models.SmallAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
("password", models.CharField(max_length=128, verbose_name="password")), ('password', models.CharField(max_length=128, verbose_name='password')),
("last_login", models.DateTimeField(blank=True, null=True, verbose_name="last login")), ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
( ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
"is_superuser", ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
models.BooleanField( ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
default=False, ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
help_text="Designates that this user has all permissions without explicitly assigning them.", ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
verbose_name="superuser status", ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
), ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
), ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
( ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')),
"username", ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')),
models.CharField(
error_messages={"unique": "A user with that username already exists."},
help_text="Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.",
max_length=150,
unique=True,
validators=[django.contrib.auth.validators.UnicodeUsernameValidator()],
verbose_name="username",
),
),
("first_name", models.CharField(blank=True, max_length=150, verbose_name="first name")),
("last_name", models.CharField(blank=True, max_length=150, verbose_name="last name")),
("email", models.EmailField(blank=True, max_length=254, verbose_name="email address")),
(
"is_staff",
models.BooleanField(
default=False,
help_text="Designates whether the user can log into this admin site.",
verbose_name="staff status",
),
),
(
"is_active",
models.BooleanField(
default=True,
help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
verbose_name="active",
),
),
("date_joined", models.DateTimeField(default=django.utils.timezone.now, verbose_name="date joined")),
(
"groups",
models.ManyToManyField(
blank=True,
help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.",
related_name="user_set",
related_query_name="user",
to="auth.group",
verbose_name="groups",
),
),
(
"user_permissions",
models.ManyToManyField(
blank=True,
help_text="Specific permissions for this user.",
related_name="user_set",
related_query_name="user",
to="auth.permission",
verbose_name="user permissions",
),
),
], ],
options={ options={
"verbose_name": "user", 'verbose_name': 'user',
"verbose_name_plural": "users", 'verbose_name_plural': 'users',
"abstract": False, 'abstract': False,
}, },
managers=[ managers=[
("objects", django.contrib.auth.models.UserManager()), ('objects', django.contrib.auth.models.UserManager()),
], ],
), ),
migrations.CreateModel( migrations.CreateModel(
name="Drink", name='Drink',
fields=[ fields=[
("id", models.SmallAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), ('id', models.SmallAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
("name", models.CharField(max_length=32, unique=True)), ('name', models.CharField(max_length=32, unique=True)),
( ('crates_ordered', models.PositiveSmallIntegerField(help_text='just informational to see how good we planned, not the actual consumed/paid drinks')),
"crates_ordered", ('crates_purchased', models.PositiveSmallIntegerField()),
models.PositiveSmallIntegerField( ('crates_returned', models.PositiveSmallIntegerField()),
help_text="just informational to see how good we planned, not the actual consumed/paid drinks" ('purchase_price_per_crate', gaehsnitz.models.PriceField(decimal_places=2, max_digits=6)),
), ('deposit_per_crate', gaehsnitz.models.PriceField(decimal_places=2, max_digits=6)),
), ('bottles_per_crate', models.PositiveSmallIntegerField()),
("crates_purchased", models.PositiveSmallIntegerField()), ('bottle_size', models.FloatField()),
("crates_returned", models.PositiveSmallIntegerField()), ('sale_price_per_bottle', gaehsnitz.models.PriceField(decimal_places=2, max_digits=6)),
("purchase_price_per_crate", gaehsnitz.models.PriceField(decimal_places=2, max_digits=6)),
("deposit_per_crate", gaehsnitz.models.PriceField(decimal_places=2, max_digits=6)),
("bottles_per_crate", models.PositiveSmallIntegerField()),
("bottle_size", models.FloatField()),
("sale_price_per_bottle", gaehsnitz.models.PriceField(decimal_places=2, max_digits=6)),
], ],
), ),
migrations.CreateModel( migrations.CreateModel(
name="Payment", name='Payment',
fields=[ fields=[
("id", models.SmallAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), ('id', models.SmallAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
("purpose", models.CharField(max_length=64)), ('purpose', models.CharField(max_length=64)),
("date", models.DateField()), ('date', models.DateField()),
("amount", gaehsnitz.models.PriceField(decimal_places=2, max_digits=6)), ('amount', gaehsnitz.models.PriceField(decimal_places=2, max_digits=6)),
( ('from_user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='payments', related_query_name='payment', to=settings.AUTH_USER_MODEL)),
"from_user",
models.ForeignKey(
on_delete=django.db.models.deletion.PROTECT,
related_name="payments",
related_query_name="payment",
to=settings.AUTH_USER_MODEL,
),
),
], ],
), ),
migrations.CreateModel( migrations.CreateModel(
name="Payback", name='Payback',
fields=[ fields=[
("id", models.SmallAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), ('id', models.SmallAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
("date", models.DateField()), ('date', models.DateField()),
("amount", gaehsnitz.models.PriceField(decimal_places=2, max_digits=6)), ('amount', gaehsnitz.models.PriceField(decimal_places=2, max_digits=6)),
("note", models.CharField(blank=True, default="", max_length=64)), ('note', models.CharField(blank=True, default='', max_length=64)),
( ('to_user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='paybacks', related_query_name='payback', to=settings.AUTH_USER_MODEL)),
"to_user",
models.ForeignKey(
on_delete=django.db.models.deletion.PROTECT,
related_name="paybacks",
related_query_name="payback",
to=settings.AUTH_USER_MODEL,
),
),
], ],
), ),
migrations.CreateModel( migrations.CreateModel(
name="Donation", name='Donation',
fields=[ fields=[
("id", models.SmallAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), ('id', models.SmallAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
("date", models.DateField()), ('date', models.DateField()),
("amount", gaehsnitz.models.PriceField(decimal_places=2, max_digits=6)), ('amount', gaehsnitz.models.PriceField(decimal_places=2, max_digits=6)),
("note", models.CharField(blank=True, default="", max_length=64)), ('note', models.CharField(blank=True, default='', max_length=64)),
( ('from_user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='donations', related_query_name='donation', to=settings.AUTH_USER_MODEL)),
"from_user",
models.ForeignKey(
on_delete=django.db.models.deletion.PROTECT,
related_name="donations",
related_query_name="donation",
to=settings.AUTH_USER_MODEL,
),
),
], ],
), ),
migrations.CreateModel( migrations.CreateModel(
name="Consumption", name='Consumption',
fields=[ fields=[
("id", models.SmallAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), ('id', models.SmallAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
("amount", models.PositiveSmallIntegerField()), ('amount', models.PositiveSmallIntegerField()),
("day", models.PositiveSmallIntegerField(choices=[(1, "Do"), (2, "Fr"), (3, "Sa")])), ('day', models.PositiveSmallIntegerField(choices=[(1, 'Do'), (2, 'Fr'), (3, 'Sa')])),
("for_free", models.BooleanField(default=False)), ('for_free', models.BooleanField(default=False)),
( ('drink', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='consumption_list', related_query_name='consumption', to='gaehsnitz.drink')),
"drink", ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='consumption_list', related_query_name='consumption', to=settings.AUTH_USER_MODEL)),
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="consumption_list",
related_query_name="consumption",
to="gaehsnitz.drink",
),
),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="consumption_list",
related_query_name="consumption",
to=settings.AUTH_USER_MODEL,
),
),
], ],
), ),
] ]
@@ -4,25 +4,26 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
("gaehsnitz", "0001_initial"), ('gaehsnitz', '0001_initial'),
] ]
operations = [ operations = [
migrations.RemoveField( migrations.RemoveField(
model_name="donation", model_name='donation',
name="from_user", name='from_user',
), ),
migrations.RemoveField( migrations.RemoveField(
model_name="payment", model_name='payment',
name="from_user", name='from_user',
), ),
migrations.AlterField( migrations.AlterField(
model_name="consumption", model_name='consumption',
name="day", name='day',
field=models.PositiveSmallIntegerField(choices=[(1, "Do"), (2, "Fr"), (3, "Sa"), (4, "So")]), field=models.PositiveSmallIntegerField(choices=[(1, 'Do'), (2, 'Fr'), (3, 'Sa'), (4, 'So')]),
), ),
migrations.DeleteModel( migrations.DeleteModel(
name="Payback", name='Payback',
), ),
] ]
+10 -7
View File
@@ -4,12 +4,14 @@ from django.db.models import Sum, F
class PriceField(models.DecimalField): class PriceField(models.DecimalField):
def __init__(self, verbose_name=None, name=None, **kwargs): def __init__(self, verbose_name=None, name=None, **kwargs):
kwargs.update({"max_digits": 6, "decimal_places": 2}) kwargs.update({"max_digits": 6, "decimal_places": 2})
super().__init__(verbose_name, name, **kwargs) super().__init__(verbose_name, name, **kwargs)
class User(AbstractUser): class User(AbstractUser):
@property @property
def paid_drinks(self): def paid_drinks(self):
return self.consumption_list.filter(for_free=False) return self.consumption_list.filter(for_free=False)
@@ -20,9 +22,9 @@ class User(AbstractUser):
@property @property
def consumed_drinks_price(self): def consumed_drinks_price(self):
query = self.paid_drinks.annotate(cost=F("amount") * F("drink__sale_price_per_bottle")).aggregate( query = self.paid_drinks \
sum=Sum("cost") .annotate(cost=F("amount") * F("drink__sale_price_per_bottle")) \
) .aggregate(sum=Sum("cost"))
return query["sum"] or 0 return query["sum"] or 0
@@ -43,6 +45,7 @@ class Payment(models.Model):
amount = PriceField() amount = PriceField()
class Drink(models.Model): class Drink(models.Model):
name = models.CharField(max_length=32, unique=True) name = models.CharField(max_length=32, unique=True)
crates_ordered = models.PositiveSmallIntegerField( crates_ordered = models.PositiveSmallIntegerField(
@@ -124,11 +127,11 @@ class Drink(models.Model):
class Consumption(models.Model): class Consumption(models.Model):
user = models.ForeignKey( user = models.ForeignKey(
to=User, on_delete=models.CASCADE, related_name="consumption_list", related_query_name="consumption" to=User, on_delete=models.CASCADE,
) related_name="consumption_list", related_query_name="consumption")
drink = models.ForeignKey( drink = models.ForeignKey(
to=Drink, on_delete=models.CASCADE, related_name="consumption_list", related_query_name="consumption" to=Drink, on_delete=models.CASCADE,
) related_name="consumption_list", related_query_name="consumption")
amount = models.PositiveSmallIntegerField() amount = models.PositiveSmallIntegerField()
day = models.PositiveSmallIntegerField(choices=[(1, "Do"), (2, "Fr"), (3, "Sa"), (4, "So")]) day = models.PositiveSmallIntegerField(choices=[(1, "Do"), (2, "Fr"), (3, "Sa"), (4, "So")])
for_free = models.BooleanField(default=False) for_free = models.BooleanField(default=False)
+17 -40
View File
@@ -11,18 +11,18 @@ table, thead, tfoot, tr, td {
html, body { html, body {
width: 100%; width: 100%;
height: 100%; height: 100%;
font-size: 16px; font-size: 14px;
} }
@media only screen and (min-width: 600px) and (max-width: 899px) { @media only screen and (min-width: 600px) and (max-width: 899px) {
html, body { html, body {
font-size: 18px; font-size: 16px;
} }
} }
@media only screen and (min-width: 900px) { @media only screen and (min-width: 900px) {
html, body { html, body {
font-size: 20px; font-size: 18px;
} }
} }
@@ -42,15 +42,8 @@ body {
flex: 0 1 auto; flex: 0 1 auto;
width: 95%; width: 95%;
max-width: 1200px; max-width: 1200px;
margin: 8px;
}
#navi, #content {
padding-bottom: 24px; padding-bottom: 24px;
} margin: 8px;
#content {
margin-top: 0;
} }
#navi, #content { #navi, #content {
@@ -59,23 +52,22 @@ body {
#title { #title {
margin-top: 24px; margin-top: 24px;
padding-bottom: 18px;
text-align: center; text-align: center;
color: #FFCC77; color: #CCEE66;
font-weight: bold; font-weight: bold;
} }
h1 { h1 {
margin-bottom: 10px; margin-bottom: 10px;
font-size: 1.6rem; font-size: 1.6rem;
color: #EE9933; color: #99EE33;
text-shadow: 0 0 16px #CC6611; text-shadow: 0 0 16px #669933;
} }
#navi { #navi {
padding: 8px 0; padding: 8px 0;
text-align: center; text-align: center;
color: #885522; color: #446622;
} }
#navi a { #navi a {
@@ -85,7 +77,7 @@ h1 {
a { a {
text-decoration: none; text-decoration: none;
color: #EE9933; color: #99EE33;
transition: color 100ms; transition: color 100ms;
} }
@@ -111,7 +103,7 @@ h2 {
margin-bottom: 14px; margin-bottom: 14px;
font-size: 1.3rem; font-size: 1.3rem;
font-weight: normal; font-weight: normal;
color: #EE9933; color: #99EE33;
} }
h3 { h3 {
@@ -119,7 +111,7 @@ h3 {
margin-bottom: 8px; margin-bottom: 8px;
font-size: 1.15rem; font-size: 1.15rem;
font-weight: normal; font-weight: normal;
color: #FFCC77; color: #CCEE66;
} }
p, ul { p, ul {
@@ -139,15 +131,15 @@ table {
} }
thead { thead {
color: #FFCC77; color: #CCEE66;
} }
.odd-row { .odd-row {
background-color: rgba(80, 40, 10, 0.4); background-color: rgba(40, 60, 20, 0.4);
} }
.even-row { .even-row {
background-color: rgba(80, 40, 10, 0.1); background-color: rgba(40, 60, 20, 0.1);
} }
td { td {
@@ -158,7 +150,7 @@ td {
hr { hr {
margin-top: 24px; margin-top: 24px;
margin-bottom: 24px; margin-bottom: 24px;
border: 3px solid #885522; border: 3px solid #446622;
border-radius: 3px; border-radius: 3px;
} }
@@ -199,7 +191,7 @@ hr {
margin-top: 12px; margin-top: 12px;
margin-bottom: 12px; margin-bottom: 12px;
border: 2px solid; border: 2px solid;
border-image: linear-gradient(to right, rgb(238, 153, 51) 0%, rgba(238, 102, 34, 0) 100%) 1; border-image: linear-gradient(to right, rgb(153, 238, 51) 0%, rgba(238, 153, 51, 0) 100%) 1;
overflow: hidden; overflow: hidden;
} }
@@ -208,7 +200,7 @@ hr {
max-width: 160px; max-width: 160px;
max-height: 90px; max-height: 90px;
z-index: -1; z-index: -1;
box-shadow: 0 0 30px #885522; box-shadow: 0 0 30px #446622;
} }
.bandbox p { .bandbox p {
@@ -257,18 +249,3 @@ hr {
.marked { .marked {
color: #CC66EE; color: #CC66EE;
} }
#footer {
margin-top: 32px;
padding-bottom: 32px;
border-bottom: 1px solid transparent;
}
/* archive pages: neutral blue-grey color scheme (content only, nav/title stay amber) */
.archive #content h2 { color: #D8DEF0; }
.archive #content h3 { color: #B8C0D8; }
.archive #content a { color: #B8C0D8; }
.archive #content thead { color: #B8C0D8; }
.archive #content .odd-row { background-color: rgba(180, 200, 255, 0.07); }
.archive #content .even-row { background-color: rgba(180, 200, 255, 0.02); }
.archive #content hr { border-color: #505870; }
@@ -1,255 +0,0 @@
{% extends "gaehsnitz/base.html" %}
{% block body_class %}archive{% endblock %}
{% block content %}
<h2>Archiv 2022</h2>
<p>25. - 28. August 2022</p>
<hr>
<h2>News</h2>
<h3>11.09. - Aftermath</h3>
<p>
Tja Leute, wie das immer so ist: lang geplant, kurz gefeiert... aber es war wieder absolut Klasse! Die bunte
Band-Mischung hat richtig gefetzt, die Versorgung hat der hohen Trichterfrequenz bei weitem standgehalten, aber
vor allem war mal wieder ein ganzer Haufen lieber Leute am Start,
<span class="accent">Danke dafür! ❤</span>
</p>
<h3>15.08. - TL;DR</h3>
<p>
In anderthalb Wochen ist es so weit, deshalb hier kurz das Wichtigste zusammengefasst:
</p>
<ul>
<li>Checkt die Anreise und bildet Fahrgemeinschaften.</li>
<li>Bringt gern Leute mit, aber fragt uns bitte vorher. Außerdem nicht im Internet posten - die Veranstaltung ist privat.</li>
<li>Bitte helft uns mit eurer Eintrittsspende und noch besser vorab mit einem Suff-Kredit. ❤</li>
<li>Suff aller Art gibt's genug und zu fairen Preisen.</li>
<li>Das Essen könnte knapp werden. Bitte bringt eine Kleinigkeit mit (Aufstriche, Salate, Käse etc.).</li>
<li>Draußen gibt es kein Trinkwasser - bringt Wasserkanister mit.</li>
</ul>
<h3>17.07. - .. es wird!</h3>
<p>
Wir haben uns dieses Wochenende noch einmal ins Zeug gelegt: einen Drehstrom-Anschluss verkabelt, die Bar neu
lackiert, den Drum-Riser gebaut, die Laube aufgeräumt und mal wieder überall gemäht.
</p>
<h3>27.05. - Himmelfahrtsaktion</h3>
<p>Am Wochenende nach Himmelfahrt haben wir schonmal gaaanz viel geschafft:</p>
<ul>
<li>Rasen gemäht und einige Büsche verschnitten</li>
<li>die Bar stabilisiert</li>
<li>die Bühnenfläche vermessen, mit Platten begrenzt und geebnet</li>
<li>die Hauptfläche weiter begradigt</li>
<li>sämtliches Holz am Grundstücksrand gestapelt</li>
</ul>
<hr>
<h2>Programm</h2>
<ul>
<li>Donnerstag 25.: Aufbau</li>
<li>Freitag 26.: Quast, Direct Juice</li>
<li>Samstag 27.: Melo-Komplott, The Residudes, RATs</li>
<li>Sonntag 28.: Abbau</li>
</ul>
<hr>
<h2>Von A bis Z</h2>
<p>
Wie letztes Jahr schon werden wir womöglich demnächst mal auswerten, wie die Dinge im Detail so gelaufen sind.
Dann wird hier alles kommentiert, damit wir uns das bis nächstes Jahr merken können. ;)
</p>
<h3 id="address">Adresse &amp; Anfahrt</h3>
<p>
Die Sause findet im Garten auf dem Grundstück von Tobis Eltern statt.
</p>
<p>
Adresse: Gähsnitzer Ring 9, 04618 Nobitz<br>
Koordinaten: 50.9070, 12.5465
</p>
<p>
Bekanntlich kann man ja im August noch für 9,-€ die Welt bereisen, daher empfiehlt sich die gemeinsame Anreise
<span class="accent">mit dem Zug</span>. Die S5X fährt stündlich um :40 von Leipzig Hbf und kommt um :25 in
Gößnitz an. Von dort sind es noch etwa 11km.
</p>
<h3 id="event">Art der Veranstaltung</h3>
<p>
Das ganze ist immer noch eine private Gartenparty, keine angemeldete Veranstaltung! Das bringt folgende Regeln
mit sich:
</p>
<ul>
<li>Bitte macht <span class="accent">keine öffentliche Werbung</span>, vor allem nicht im Internet.</li>
<li>Ihr könnt Freund*innen mitbringen, aber bitte fragt uns vorher mal kurz.</li>
<li>Achtet auf das Wohl der Anwohner*innen.</li>
<li>Live-Mucke sollte bis 22:00 durch sein. Danach können wir immer noch Konservenmucke hören, aber am besten nur auf 70% Lautstärke. ;)</li>
</ul>
<h3 id="food">Essen</h3>
<p>
Hauptmahlzeiten: Am Donnerstag werden wir wohl den Grill anhauen. Am Freitag und Samstag wird es jeweils eine
vegane Hauptmahlzeit aus dem großen Feuertopf geben.
</p>
<p>
Rundherum bitten wir euch, euch <span class="accent">selbst etwas zu essen mitzubringen</span> - Aufstriche,
Salate, Käse etc. in verschließbaren Behältern. Wir besorgen Brot/Brötchen und einen Grundvorrat.
</p>
<h3 id="drinks">Getränke &amp; Bar</h3>
<p>
Ein lokaler Getränkehändler bringt uns 'nen LKW voll Suff vorbei - es gibt Bier, Radler, Wasser, Mate und Cola.
Alles wird in Flaschen verkauft, seid deshalb bitte besonders vorsichtig, dass nichts zu Bruch geht!
</p>
<h3>Mucke &amp; Playlists</h3>
<p>
DJ Hymr wird einen Haufen Mucke bereithalten. Darüber hinaus gibt es Klinkenparty, allerdings streng limitiert
von den Geschmäckern der Veranstalter. :P
</p>
<h3>Parken &amp; Zelten</h3>
<p>
Der Großteil des Gartens (hinter der Bühne) dient als Zeltplatz. Es gibt einige Parkplätze rund um das
Grundstück und die Garage.
</p>
<h3 id="sanitary">Sanitär</h3>
<p>
<span class="accent">Es gibt kein Wasser auf dem Gelände!</span> Wenn ihr die Möglichkeit habt, bringt bitte
größtmögliche <span class="accent">Wasserkanister</span> (auch leer) mit. Es wird Dixi-Toiletten mit
Desinfektionsmittel und einem mobilen Waschbecken geben.
</p>
<h3>Wetter</h3>
<p>
Wir haben viele Pavillons, um auch bei Regen noch einigermaßen gute Laune zu wahren. Haltet Abstand mit Feuer
zur Vegetation und werft keine Kippen in die Gegend!
</p>
<hr>
<h2>Bühne &amp; Technik</h2>
<h3>Backline</h3>
<ul>
<li>Bassbox: Markbass 4x10", 4 Ohm, Speakon</li>
<li>Gitarrenbox: JetCity 2x12", 8 Ohm, Klinke</li>
<li>Drums: Pearl, Bassdrum, 3 Toms, Stative für Snare, HiHat, Crash, Ride</li>
<li>(Bass-Amp: Markbass Little Mark Tube 800 darf mitgenutzt werden)</li>
<li>(Gitarrenkombo: Blackstar HT-5 darf mitbenutzt werden)</li>
</ul>
<h3>Mikrofonierung</h3>
<ul>
<li>3 Gesangsmikros: SM58, PG58 und noch 'n billiges</li>
<li>3 Amp/Instrumenten-Mikros (Bass sowieso lieber via DI)</li>
<li>Drum-Mikros: t.bone Beta BD 500 und ein Set für alles andere</li>
<li>1 DI-Box</li>
<li>6 große Mikro-Stative, 3 kleine Mikro-Stative</li>
</ul>
<h3>Monitoring</h3>
<ul>
<li>1 Aktivbox neben den Drums</li>
<li>2 Front-Monitore (RATs)</li>
</ul>
<h3>PA</h3>
<ul>
<li>Mischpult &amp; Stagebox: Behringer X-Air 18</li>
<li>Beschallung: 2 aktive Subwoofer, 2 passive Hochtöner + Amp, Stative</li>
</ul>
<hr>
<h2>Finanzen</h2>
<p>
Da eine offene Kommunikation irgendwie zu dem ganzen unkommerziellen DIY-Gedöhns dazugehört, findet ihr hier
ganz transparent eine Übersicht, von wo nach wo eigentlich wie viel Kohle geflossen ist.
Nur keine Klarnamen. ;)
</p>
<h3>Zusammenfassung</h3>
<table>
<tr class="odd-row">
<td>Summe aller Spenden/Zahlungen</td>
<td>1.130 €</td>
</tr>
<tr class="even-row">
<td>Summe aller Ausgaben</td>
<td>1.250 €</td>
</tr>
<tr class="odd-row">
<td>Stand</td>
<td class="accent">-120 €</td>
</tr>
</table>
<h3>Ausgaben</h3>
<table>
<thead>
<tr class="odd-row">
<td>Zweck</td>
<td>Betrag</td>
<td>Datum</td>
</tr>
</thead>
<tr class="even-row">
<td>Baumarkt/Elektrik</td>
<td>70 €</td>
<td>16.07.</td>
</tr>
<tr class="odd-row">
<td>Baumarkt/Elektrik</td>
<td>27 €</td>
<td>18.07.</td>
</tr>
<tr class="even-row">
<td>Dixis</td>
<td>328 €</td>
<td>08.08.</td>
</tr>
<tr class="odd-row">
<td>Getränke/Anzahlung</td>
<td>400 €</td>
<td>22.08.</td>
</tr>
<tr class="even-row">
<td>Supermarkt/Essen</td>
<td>193 €</td>
<td>25.08.</td>
</tr>
<tr class="odd-row">
<td>Getränke/Abrechnung</td>
<td>122 €</td>
<td>01.09.</td>
</tr>
<tr class="even-row">
<td>Bands</td>
<td>110 €</td>
<td>-</td>
</tr>
</table>
<p>
Details zu den Spenden und Rückzahlungen an die Leute, die die Ausgaben geleistet haben,
lassen wir hier erstmal weg. Wer's ganz genau wissen will, kann ja fragen.
</p>
<p>
Nicht aufgelistet sind kurzfristige Dinge für die Vorbereitungsaktionen, also z.B. Suff und Sprit, den wir für
die Arbeitseinsätze gekauft und auch direkt vernichtet haben. Danke an dieser Stelle nochmal allen für die
jeweiligen Einkäufe und die unbezahlbare Arbeitskraft!
</p>
{% endblock %}
@@ -1,273 +0,0 @@
{% extends "gaehsnitz/base.html" %}
{% load static %}
{% load money %}
{% block body_class %}archive{% endblock %}
{% block content %}
<h2>Archiv 2024</h2>
<p>06. - 09. Juni 2024</p>
<hr>
<h2>News</h2>
<h3>06.05. - Hochoffizielle Einladung</h3>
<p>
Der Plan für Gähsnitz dieses Jahr steht und zur Motivation gibt's diesmal auch 'n digitales Plakat. 🍾
</p>
<a href="{% static 'gaehsnitz/plakat-2024.jpg' %}">
<img id="flyer" src="{% static 'gaehsnitz/plakat-2024-small.jpg' %}" alt="Plakat">
</a>
<p>
Fühlt euch alle eingeladen, am 6., 7., spätestens aber am 8. Juni bei uns im Garten vorbeizuschneien. Es gibt
bunt gemischte Live-Musik, Getränke für'n schmalen Taler, echte Landluft und was sonst noch alles auf dem Bild
zu finden ist.
</p>
<p>
Mehr Details gibt's nochmal 1-2 Wochen vorher - bis dahin einfach den Termin freihalten, Urlaub nehmen oder
kündigen, und am besten auch schonmal üben, wie man ganz schnell Pavillons aufbaut und Wurfzelte wieder in ihre
Verpackung kriegt.
</p>
<p>
Bringt gern noch mehr liebe Leute mit, aber bitte nich bei MySpace posten oder Plakate aufhängen - ist immer
noch 'ne Privatveranstaltung. ;)
</p>
<h3>04.04. - Der Winterschlaf ist vorbei</h3>
<p>
Der Termin für unsere diesjährige Gartensause steht ja schon seit letztem Jahr fest:
<span class="accent">06. - 09. Juni</span>. Sogar die Dixis sind schon vorbestellt! Den größten Fokus (und die
meiste Live-Mucke) wollen wir dieses Mal auf Samstag (08.06.) legen, aber mehr dazu später.
</p>
<p>
Über Ostern waren haben wir uns mal das Gelände angeschaut und uns gefreut, dass sich in anderthalb Jahren gar
nicht mal so viel verändert hat - sogar das Drum-Podest ist noch nutzbar. Trotzdem gibt's natürlich alle Hände
voll zu tun, um den Garten wieder festivaltauglich zu machen und zu konservieren.
</p>
<p>
Wir wollen über <span class="accent">Himmelfahrt</span> (09. - 12.05.) nochmal hinfahren und könnten dafür auch
so viele helfende Hände wie möglich gebrauchen. Wer also Bock auf Handarbeit, kühle Getränke und Feuermachen in
der Pampa hat, bitte melden! :)
</p>
<p>
Nun zur To-do-Liste: zum einen gibt's viel zu <span class="accent">gärtnern</span>:
</p>
<ul>
<li>Rasen mähen</li>
<li>"Palisade" befestigen, damit sie nicht zu breit wird</li>
<li>Efeu vom Boden entfernen / Fläche neben dem Schuppen wieder nutzbar machen</li>
<li>Bäume, Büsche und Hecken auf dem Gelände verschneiden (auch überm Dach der Laube)</li>
<li>Bäume und Büsche an den Grundstücksgrenzen verschneiden (vor allem oben an der Ecke)</li>
<li>Todholz einsammeln und die Palisade erweitern / Feuerholz separat sammeln</li>
<li>Müll/Schrott sammeln</li>
<li>neuen Rasen sähen</li>
</ul>
<p>
Zum anderen gibt es Folgendes zu <span class="accent">bauen</span>:
</p>
<ul>
<li>
Bar: neue OSB-Platte drauf schrauben, nochmal lackieren<br>
Maße: 310 lang, 63 breit
</li>
<li>
Erde auf der Bühne aufschütten und neu ebnen, womöglich noch ein paar Steinplatten dazulegen
</li>
<li>
Treppe zur Laube bzw. zur "Hochebene" bauen (Erde kann für Bühne genutzt werden)
</li>
<li>
Drum-Podest erneuern: marode Stellen mit Ziegelsteinen befestigen, OSB-Platten drauf schrauben,
lackieren<br>
Maße: 240 breit, 160 lang
</li>
<li>
lose Paletten streichen
</li>
<li>
<del>Plumpsklo: Wände putzen, neuen Boden bauen, neue Sitzbank bauen, Brille besorgen</del>
<br>
Maße Sitzbank: 70 breit, 50 tief
</li>
</ul>
<p>
Hier ist der <span class="accent">Einkaufszettel</span> dafür:
</p>
<ul>
<li>Rasensamen, z.B. 5 kg für 200 m² - 30 €</li>
<li>Bar: OSB-Platte, z.B. 250x125 cm längs halbiert, 18 mm stark, 37 €</li>
<li>Drum-Podest: OSB-Verlegeplatten, z.b. 4x 205x67 cm, 25 mm stark, 80 €</li>
<li>Holzfarbe: z.B. Wetterschutzfarbe schwedenrot 2,5 l (reicht für Bar und Podest), 38 €</li>
<li>Holzlasur: z.B. 10 l Kanister, 10 €</li>
<li>
<del>Plumpsklo</del>
</li>
</ul>
<p>&rarr; ca. 200 €</p>
<p>
Und weil's so schön ist, hier noch ein paar Impressionen, Stand 30.03.:
</p>
<div class="image-list">
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/feld-eingang-auszen.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/feld-eingang-innen.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/bar-fern.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/bar-nah.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/buehne-bar-palisade.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/buehne.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/laube-von-unten.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/laube-von-vorn.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/laube-von-oben.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/laube-dach.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/haus-zeltplatz.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/strasze-eingang.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/haus-buesche.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/haus-feuerholz.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/unten-gewaechshaus.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/unten-wiese.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/unten-rand.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/schuppen.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/rand-efeu.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/rand-pissecke.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/rand-waeldchen.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/rand-zaun.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/rand-portal.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/grosze-tanne.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/strasze-kirschen.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/strasze-hecke.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/strasze-oben.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/feld-spaghetti.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/feld-rand.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/plumpsklo.jpg' %}" alt=""></div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/plumpsklo-boden.jpg' %}" alt=""></div>
</div>
<hr>
<h2>Programm</h2>
<ul>
<li>Donnerstag 06.: ganz viel Aufbau</li>
<li>Freitag 07.: Warm-Up</li>
<li>Samstag 08.: ganz viel Live-Mucke</li>
<li>Sonntag 09.: ganz viel Abbau</li>
</ul>
<hr>
<h2>Bühne &amp; Technik</h2>
<p>zur Info für Künstler*innen und als Packliste für uns ;)</p>
<h3>Backline</h3>
<ul>
<li>
Drums:<br>
(Josi) Bassdrum, 2 Toms, Floor-Tom, Hocker, Stative für Snare, HiHat, Crash und Ride<br>
(Josi) Snare (nur für Open Stage)<br>
(Flo) Iron Cobra 600 Double Bass Pedal (darf für alles mitbenutzt werden)<br>
(Tobi) HiHat, Crash, Ride (nur für Open Stage)
</li>
<li>Bassbox: Markbass 4x10", 4 Ohm, Speakon</li>
<li>(Bass-Topteil: Markbass Little Mark Tube 800 darf mitbenutzt werden)</li>
<li>Gitarrenbox: Palmer 2x12", 8 Ohm, Klinke</li>
<li>(Gitarrenkombo: Blackstar HT-5 darf mitbenutzt werden)</li>
</ul>
<h3>Mikrofonierung</h3>
<ul>
<li>Kick: t.bone Beta 500</li>
<li>Snare: SM57</li>
<li>Toms: 3x Audix f2</li>
<li>Overheads: 2x Rode M5</li>
<li>Amps: 3x Superlux Grenzfläche</li>
<li>DI: 1x Behringer DI-Box (Mono)</li>
<li>Gesang: 1x Beta 58, 1x SM58 (Sepp), 1x Superlux</li>
<li>Stative: mal Inventur machen ...</li>
</ul>
<h3>Monitoring</h3>
<ul>
<li>3 Boxen angefragt mit der PA, noch in Klärung ...</li>
</ul>
<h3>PA</h3>
<ul>
<li>Mischpult &amp; Stagebox: Behringer X-Air 18</li>
<li>Beschallung: HK-Audio Pro, 2 18"-Subs, 2 Tops, aktiv</li>
</ul>
<h3>Beleuchtung</h3>
<ul>
<li>2x Bars mit jeweils 4 LED-Spots</li>
<li>Superfly</li>
<li>DMX-Steuerung über Laptop möglich</li>
</ul>
<h3>Kabel</h3>
<ul>
<li>24x XLR (16 Channels, 3 Monitore, 4 PA, 1 Reserve)</li>
<li>2x XLR-Male ↔ Klinke</li>
<li>13x Kaltgeräte-Stecker (Mixer, Markbass, Blackstar, 3 Monitore, 4 PA, 1 Lampe, 1 Reserve)</li>
<li>2x Kaltgeräte-Verlängerung (zwischen Lampen)</li>
<li>4x DMX (3 Lampen, 1 Reserve)</li>
<li>...</li>
</ul>
<hr>
<h2>Finanzen</h2>
<p>
Da eine offene Kommunikation irgendwie zu dem ganzen unkommerziellen DIY-Gedöhns dazugehört, findet ihr hier
ganz transparent eine Übersicht, von wo nach wo eigentlich wie viel Kohle geflossen ist.
Nur keine Klarnamen. ;)
</p>
<h3>Zusammenfassung</h3>
<table>
<tr class="odd-row">
<td>Summe aller Spenden/Zahlungen</td>
<td>{{ total_donations|euro }}</td>
</tr>
<tr class="even-row-row">
<td>Summe aller Ausgaben</td>
<td>{{ total_payments|euro }}</td>
</tr>
<tr class="odd-row">
<td>Stand</td>
<td class="accent">{{ total_balance|euro }}</td>
</tr>
</table>
<h3>Ausgaben</h3>
<table>
<thead>
<tr class="odd-row">
<td>Zweck</td>
<td>Betrag</td>
<td>Datum</td>
</tr>
</thead>
{% for payment in payments %}
<tr class="{% cycle 'even-row' 'odd-row' %}">
<td>{{ payment.purpose }}</td>
<td>{{ payment.amount|euro }}</td>
<td>{% if payment.date %}{{ payment.date|date:"d.m." }}{% else %}-{% endif %}</td>
</tr>
{% endfor %}
</table>
<p>
Details zu den Spenden und Rückzahlungen an die Leute, die die Ausgaben geleistet haben,
lassen wir hier erstmal weg. Wer's ganz genau wissen will, kann ja fragen.
</p>
<p>
Nicht aufgelistet sind kurzfristige Dinge für die Vorbereitungsaktionen, also z.B. Suff und Sprit, den wir für
die Arbeitseinsätze gekauft und auch direkt vernichtet haben. Danke an dieser Stelle nochmal allen für die
jeweiligen Einkäufe und die unbezahlbare Arbeitskraft!
</p>
{% endblock %}
+9
View File
@@ -0,0 +1,9 @@
{% extends "gaehsnitz/base.html" %}
{% load static %}
{% block content %}
<h2>&#128736; Alles noch in Planung</h2>
<p>Bald gibt's mehr Infos.</p>
{% endblock %}
+22 -12
View File
@@ -1,25 +1,35 @@
{% load static %} {% load static %}
<!doctype html> <!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8" /> <meta charset="utf-8">
<title>Gähsnitz Open Air</title> <title>Gähsnitz Open Air</title>
<link rel="stylesheet" type="text/css" href="{% static 'gaehsnitz/style.css' %}" /> <link rel="stylesheet" type="text/css" href="{% static 'gaehsnitz/style.css' %}">
</head> </head>
<body class="{% block body_class %}{% endblock %}"> <body>
<div id="title"> <div id="title">
<h1>Gähsnitz Open Air 2026</h1> <h1>Gähsnitz Open Air 2024</h1>
~ Do 11. - So 14. Juni ~ ~ Do 06. - So 09. Juni ~
</div> </div>
<div id="content">{% block content %}{% endblock %}</div> <div id="navi">
<a href="{% url 'gaehsnitz:news' %}">News</a>
<div id="footer">
<a href="{% url 'gaehsnitz:archive-2022' %}">Archiv 2022</a>
| |
<a href="{% url 'gaehsnitz:archive-2024' %}">Archiv 2024</a> <a href="{% url 'gaehsnitz:atoz' %}">A-Z</a>
|
<a href="{% url 'gaehsnitz:program' %}">Programm</a>
|
<a href="{% url 'gaehsnitz:finance' %}">Finanzen</a>
|
<a href="{% url 'gaehsnitz:for-bands' %}">für Bands</a>
</div> </div>
<div id="content">
{% block content %}{% endblock %}
</div>
</body> </body>
</html> </html>
@@ -0,0 +1,62 @@
{% extends "gaehsnitz/base.html" %}
{% load money %}
{% block content %}
<h2>&#128736; Abwarten</h2>
<p>Auch hier wird noch geplant ...</p>
<h2>Details</h2>
<p>
Da eine offene Kommunikation irgendwie zu dem ganzen unkommerziellen DIY-Gedöhns dazugehört, findet ihr hier
ganz transparent eine Übersicht, von wo nach wo eigentlich wie viel Kohle geflossen ist.
Nur keine Klarnamen. ;)
</p>
<h3>Zusammenfassung</h3>
<table>
<tr class="odd-row">
<td>Summe aller Spenden/Zahlungen</td>
<td>{{ total_donations|euro }}</td>
</tr>
<tr class="even-row-row">
<td>Summe aller Ausgaben</td>
<td>{{ total_payments|euro }}</td>
</tr>
<tr class="odd-row">
<td>Stand</td>
<td class="accent">{{ total_balance|euro }}</td>
</tr>
</table>
<h3>Ausgaben</h3>
<table>
<thead>
<tr class="odd-row">
<td>Zweck</td>
<td>Betrag</td>
<td>Datum</td>
</tr>
</thead>
{% for payment in payments %}
<tr class="{% cycle 'even-row' 'odd-row' %}">
<td>{{ payment.purpose }}</td>
<td>{{ payment.amount|euro }}</td>
<td>{% if payment.date %}{{ payment.date|date:"d.m." }}{% else %}-{% endif %}</td>
</tr>
{% endfor %}
</table>
<p>
Details zu den Spenden und Rückzahlungen an die Leute, die die Ausgaben geleistet haben,
lassen wir hier erstmal weg. Wer's ganz genau wissen will, kann ja fragen.
</p>
<p>
Nicht aufgelistet sind kurzfristige Dinge für die Vorbereitungsaktionen, also z.B. Suff und Sprit, den wir für
die Arbeitseinsätze gekauft und auch direkt vernichtet haben. Danke an dieser Stelle nochmal allen für die
jeweiligen Einkäufe und die unbezahlbare Arbeitskraft!
</p>
{% endblock %}
@@ -0,0 +1,64 @@
{% extends "gaehsnitz/base.html" %}
{% block content %}
<h2>Bühne &amp; Technik</h2>
<p>zur Info für Künstler*innen und als Packliste für uns ;)</p>
<h3>Backline</h3>
<ul>
<li>
Drums:<br>
(Josi) Bassdrum, 2 Toms, Floor-Tom, Hocker, Stative für Snare, HiHat, Crash und Ride<br>
(Josi) Snare (nur für Open Stage)<br>
(Flo) Iron Cobra 600 Double Bass Pedal (darf für alles mitbenutzt werden)<br>
(Tobi) HiHat, Crash, Ride (nur für Open Stage)
</li>
<li>Bassbox: Markbass 4x10", 4 Ohm, Speakon</li>
<li>(Bass-Topteil: Markbass Little Mark Tube 800 darf mitbenutzt werden)</li>
<li>Gitarrenbox: Palmer 2x12", 8 Ohm, Klinke</li>
<li>(Gitarrenkombo: Blackstar HT-5 darf mitbenutzt werden)</li>
</ul>
<h3>Mikrofonierung</h3>
<ul>
<li>Kick: t.bone Beta 500</li>
<li>Snare: SM57</li>
<li>Toms: 3x Audix f2</li>
<li>Overheads: 2x Rode M5</li>
<li>Amps: 3x Superlux Grenzfläche</li>
<li>DI: 1x Behringer DI-Box (Mono)</li>
<li>Gesang: 1x Beta 58, 1x SM58 (Sepp), 1x Superlux</li>
<li class="marked">Stative: mal Inventur machen ...</li>
</ul>
<h3>Monitoring</h3>
<ul>
<li class="marked">3 Boxen angefragt mit der PA, noch in Klärung ...</li>
</ul>
<h3>PA</h3>
<ul>
<li>Mischpult &amp; Stagebox: Behringer X-Air 18</li>
<li>Beschallung: HK-Audio Pro, 2 18"-Subs, 2 Tops, aktiv</li>
</ul>
<h3>Beleuchtung</h3>
<ul>
<li>2x Bars mit jeweils 4 LED-Spots</li>
<li>Superfly</li>
<li>DMX-Steuerung über Laptop möglich</li>
</ul>
<h3>Kabel</h3>
<ul>
<li>24x XLR (16 Channels, 3 Monitore, 4 PA, 1 Reserve)</li>
<li>2x XLR-Male ↔ Klinke</li>
<li>13x Kaltgeräte-Stecker (Mixer, Markbass, Blackstar, 3 Monitore, 4 PA, 1 Lampe, 1 Reserve)</li>
<li>2x Kaltgeräte-Verlängerung (zwischen Lampen)</li>
<li>4x DMX (3 Lampen, 1 Reserve)</li>
<li>...</li>
</ul>
{% endblock %}
+151 -129
View File
@@ -1,146 +1,168 @@
{% extends "gaehsnitz/base.html" %} {% load money %} {% block content %} {% extends "gaehsnitz/base.html" %}
{% load static %}
<h2>Gähsnitz Open Air</h2> {% block content %}
<p>Unser eigenes kleines Festival ... oder auch nur eine große Gartenparty.</p>
<p>--- Plakat folgt ---</p>
<p>Do 11. bis So 14. Juni 2026</p>
<p>Gähsnitzer Ring 9, 04603 Nobitz</p>
<p>Live-Bands: Knast, Kotpiloten, Melo-Komplott, Mörtel, Quast</p>
<h2>Allgemeine Infos</h2> <h2>06.05. - Hochoffizielle Einladung</h2>
<p>💰 Eintritt gegen Spende. Getränke für'n schmalen Taler. Beides hilft uns sehr bei der Finanzierung. :)</p>
<p>🤫 Es ist eine Privatparty - bitte keine öffentliche Werbung machen! Bringt aber gern Freund*innen mit.</p>
<p> <p>
⛺ Zelten könnt ihr im Garten selbst oder auf der Wiese dahinter. Parken vor dem Grundstück oder ebenfalls hinten Der Plan für Gähsnitz dieses Jahr steht und zur Motivation gibt's diesmal auch 'n digitales Plakat. 🍾
auf der Wiese. </p>
<a href="{% static 'gaehsnitz/plakat-2024.jpg' %}">
<img id="flyer" src="{% static 'gaehsnitz/plakat-2024-small.jpg' %}" alt="Plakat">
</a>
<p>
Fühlt euch alle eingeladen, am 6., 7., spätestens aber am 8. Juni bei uns im Garten vorbeizuschneien. Es gibt
bunt gemischte Live-Musik, Getränke für'n schmalen Taler, echte Landluft und was sonst noch alles auf dem Bild
zu finden ist.
</p> </p>
<p> <p>
🚉 Der nächste Bahnhof ist in Gößnitz, mit dem Auto 13km / 17min entfernt, mit dem Fahrrad 12km / 40min. Die S5 bzw. Mehr Details gibt's nochmal 1-2 Wochen vorher - bis dahin einfach den Termin freihalten, Urlaub nehmen oder
S5X von Leipzig Hbf fährt jede halbe Stunde, um :28 und :58. Fragt uns ansonsten gern nach Mitfahrgelegenheiten! kündigen, und am besten auch schonmal üben, wie man ganz schnell Pavillons aufbaut und Wurfzelte wieder in ihre
Verpackung kriegt.
</p> </p>
<p>🔊 Achtet auf Anwohner*innen - Live-Mucke gibt's bis 22:00, danach Party auf 70% Lautstärke.</p>
<p>🔥 Seid vorsichtig mit offenem Feuer und werft keinen Müll (auch Kronkorken) in den Garten.</p>
<p> <p>
🍲 Es gibt eine vegane Hauptmahlzeit (ebenfalls für'n schmalen Taler) am Freitag und Samstag. Versorgt euch darüber Bringt gern noch mehr liebe Leute mit, aber bitte nich bei MySpace posten oder Plakate aufhängen - ist immer
hinaus bitte selbst. Es gibt Sandwich-Maker, also könnt ihr gern Toast und Zutaten dafür mitbringen. noch 'ne Privatveranstaltung. ;)
</p> </p>
<p>🚽 Es gibt Dixis, Desinfektionsmittel und eine Wasserstelle mit Gartenschlauch (Trinkwasser) - keine Dusche.</p>
<hr /> <hr>
<h2>Für Bands</h2> <h2>04.04. - Der Winterschlaf ist vorbei</h2>
<p>
<h3>Konditionen</h3> Der Termin für unsere diesjährige Gartensause steht ja schon seit letztem Jahr fest:
<span class="accent">06. - 09. Juni</span>. Sogar die Dixis sind schon vorbestellt! Den größten Fokus (und die
meiste Live-Mucke) wollen wir dieses Mal auf Samstag (08.06.) legen, aber mehr dazu später.
</p>
<p>
Über Ostern waren haben wir uns mal das Gelände angeschaut und uns gefreut, dass sich in anderthalb Jahren gar
nicht mal so viel verändert hat - sogar das Drum-Podest ist noch nutzbar. Trotzdem gibt's natürlich alle Hände
voll zu tun, um den Garten wieder festivaltauglich zu machen und zu konservieren.
</p>
<p>
Wir wollen über <span class="accent">Himmelfahrt</span> (09. - 12.05.) nochmal hinfahren und könnten dafür auch
so viele helfende Hände wie möglich gebrauchen. Wer also Bock auf Handarbeit, kühle Getränke und Feuermachen in
der Pampa hat, bitte melden! :)
</p>
<p>
Nun zur To-do-Liste: zum einen gibt's viel zu <span class="accent">gärtnern</span>:
</p>
<ul> <ul>
<li>Mindestens Spritkohle, darüber hinaus Gage, mit der ihr euch wohlfühlt ;)</li> <li>Rasen mähen</li>
<li>Getränke und eine warme Mahlzeit am Spieltag kostenlos</li> <li>"Palisade" befestigen, damit sie nicht zu breit wird</li>
<li>Keine Schlafplätze und keine Dusche nur Camping (Wasserstelle gibt's)</li> <li>Efeu vom Boden entfernen / Fläche neben dem Schuppen wieder nutzbar machen</li>
<li>Wenig Bands / kein Zeitdruck, aber 22:00 sollte die Live-Mucke langsam fertig sein</li> <li>Bäume, Büsche und Hecken auf dem Gelände verschneiden (auch überm Dach der Laube)</li>
<li>Bäume und Büsche an den Grundstücksgrenzen verschneiden (vor allem oben an der Ecke)</li>
<li>Todholz einsammeln und die Palisade erweitern / Feuerholz separat sammeln</li>
<li>Müll/Schrott sammeln</li>
<li>neuen Rasen sähen</li>
</ul> </ul>
<p>
<h3>Ablauf</h3> Zum anderen gibt es Folgendes zu <span class="accent">bauen</span>:
<p>vorläufig kann diskutiert, verschoben und vertauscht werden</p> </p>
<p>Donnerstag: Aufbau, Grundeinstellung, Soundcheck, evtl. Jam-Session &#x1F60E;</p>
<p>Freitag:</p>
<ul> <ul>
<li>18:45 Umbau + Line-Check Melo-Komplott</li> <li>
<li>19:30 Melo-Komplott</li> Bar: neue OSB-Platte drauf schrauben, nochmal lackieren<br>
<li>20:30 Umbau + Line-Check Mörtel</li> Maße: 310 lang, 63 breit
<li>21:00 Mörtel</li> </li>
<li>
Erde auf der Bühne aufschütten und neu ebnen, womöglich noch ein paar Steinplatten dazulegen
</li>
<li>
Treppe zur Laube bzw. zur "Hochebene" bauen (Erde kann für Bühne genutzt werden)
</li>
<li>
Drum-Podest erneuern: marode Stellen mit Ziegelsteinen befestigen, OSB-Platten drauf schrauben,
lackieren<br>
Maße: 240 breit, 160 lang
</li>
<li>
lose Paletten streichen
</li>
<li>
<del>Plumpsklo: Wände putzen, neuen Boden bauen, neue Sitzbank bauen, Brille besorgen</del>
<br>
Maße Sitzbank: 70 breit, 50 tief
</li>
</ul> </ul>
<p>Samstag:</p> <p>
Hier ist der <span class="accent">Einkaufszettel</span> dafür:
</p>
<ul> <ul>
<li>16:30 Umbau + Line-Check Kotpiloten</li> <li>Rasensamen, z.B. 5 kg für 200 m² - 30 €</li>
<li>17:00 Kotpiloten</li> <li>Bar: OSB-Platte, z.B. 250x125 cm längs halbiert, 18 mm stark, 37 €</li>
<li>18:00 Essenspause</li> <li>Drum-Podest: OSB-Verlegeplatten, z.b. 4x 205x67 cm, 25 mm stark, 80 €</li>
<li>18:45 Umbau + Line-Check Knast</li> <li>Holzfarbe: z.B. Wetterschutzfarbe schwedenrot 2,5 l (reicht für Bar und Podest), 38 €</li>
<li>19:15 Knast</li> <li>Holzlasur: z.B. 10 l Kanister, 10 €</li>
<li>20:15 Umbau + Line-Check Quast</li> <li>
<li>20:45 Quast</li> <del>Plumpsklo</del>
</li>
</ul> </ul>
<p>&rarr; ca. 200 €</p>
<h3>Backline für alle</h3> <p>
<p>Drums von Josi bitte mit &#x2764; behandeln</p> Und weil's so schön ist, hier noch ein paar Impressionen, Stand 30.03.:
<ul> </p>
<li>Bassdrum</li> <div class="image-list">
<li>1 Hänge- + 2 Standtoms</li> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/feld-eingang-auszen.jpg' %}" alt="">
<li>Stative für Snare, Hi-Hat, 1x Crash und 1x Ride</li> </div>
<li>Drum-Hocker</li> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/feld-eingang-innen.jpg' %}" alt="">
<li>Bassbox: Markbass 4x10", 4 Ohm, Speakon</li> </div>
<li>Gitarrenbox: <span class="marked">Ohli/Steve fragen / reicht eine?</span></li> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/bar-fern.jpg' %}" alt="">
</ul> </div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/bar-nah.jpg' %}" alt="">
<h3>Was mitgenutzt werden kann ...</h3> </div>
<ul> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/buehne-bar-palisade.jpg' %}" alt="">
<li>Bass-Topteil: Markbass Little Mark Tube 800</li> </div>
<li>Git.-Topteil: EVH 5150</li> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/buehne.jpg' %}" alt="">
<li>Git.-Kombo: Blackstar HT-5</li> </div>
<li>Fußmaschine: Iron Cobra 600 Double</li> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/laube-von-unten.jpg' %}" alt="">
</ul> </div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/laube-von-vorn.jpg' %}" alt="">
<h3>Bitte mitbringen ...</h3> </div>
<ul> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/laube-von-oben.jpg' %}" alt="">
<li>Snare</li> </div>
<li>Becken</li> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/laube-dach.jpg' %}" alt="">
<li>Fußmaschine (wenn ihr feste zutretet)</li> </div>
<li>Mehr Beckenständer, wenn die o.g. nicht reichen</li> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/haus-zeltplatz.jpg' %}" alt="">
<li>Topteil / Kombos (wenn ihr lieber eigene nutzt)</li> </div>
<li>Instrumente, Pedale, Kleinkram ...</li> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/strasze-eingang.jpg' %}" alt="">
<li>Gesangsmikros (wenn ihr gern eigene nutzt)</li> </div>
<li>Spezialmikros (wenn die u.g. nicht reichen)</li> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/haus-buesche.jpg' %}" alt="">
</ul> </div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/haus-feuerholz.jpg' %}" alt="">
<h3>Nur zum Jammen / was wir ungern verleihen ...</h3> </div>
<ul> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/unten-gewaechshaus.jpg' %}" alt="">
<li>Snare (Josi)</li> </div>
<li>Becken: Crash, Ride, HiHat (Tobi)</li> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/unten-wiese.jpg' %}" alt="">
</ul> </div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/unten-rand.jpg' %}" alt="">
<h3>Mikrofonierung</h3> </div>
<ul> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/schuppen.jpg' %}" alt="">
<li>Kick: t.bone Beta 500 | Sennheiser E902</li> </div>
<li>Snare: Shure SM57 | SE Electronics V7 X</li> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/rand-efeu.jpg' %}" alt="">
<li>Toms: 3x Audix f2</li> </div>
<li>Overheads: 2x Rode M5</li> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/rand-pissecke.jpg' %}" alt="">
<li>Amps: 1x Sennheiser E609 | 2x Superlux PRA 628</li> </div>
<li>Gesang: 1x Shure Beta 58 | <span class="marked">noch ein paar auftreiben</span></li> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/rand-waeldchen.jpg' %}" alt="">
<li>DI: <span class="marked">im Proberaum schauen / ausleihen</span></li> </div>
<li>Stative: <span class="marked">mal Inventur machen</span></li> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/rand-zaun.jpg' %}" alt="">
</ul> </div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/rand-portal.jpg' %}" alt="">
<h3>Monitoring</h3> </div>
<ul> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/grosze-tanne.jpg' %}" alt="">
<li class="marked">2x Alto Proberaum-PA reservieren</li> </div>
<li class="marked">1x JBL alte Proberaum-PA ausprobieren</li> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/strasze-kirschen.jpg' %}" alt="">
</ul> </div>
<div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/strasze-hecke.jpg' %}" alt="">
<h3>PA</h3> </div>
<ul> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/strasze-oben.jpg' %}" alt="">
<li>Mischpult &amp; Stagebox: Behringer X-Air 18</li> </div>
<li class="marked">Tablet: Enni fragen</li> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/feld-spaghetti.jpg' %}" alt="">
<li>Beschallung: HK-Audio Pro, 2 Subs, 2 Tops, aktiv</li> </div>
</ul> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/feld-rand.jpg' %}" alt="">
</div>
<h3>Beleuchtung</h3> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/plumpsklo.jpg' %}" alt="">
<ul> </div>
<li class="marked">Carsten / Jakob fragen?</li> <div class="image-wrapper"><img src="{% static 'gaehsnitz/photos-2024-03-30/plumpsklo-boden.jpg' %}" alt="">
</ul> </div>
</div>
<h3>Kabel</h3>
<ul>
<li class="marked">Liste vom letzten mal nachzählen</li>
<li>24x XLR (16 Channels, 3 Monitore, 4 PA, 1 Reserve)</li>
<li>2x XLR-Male ↔ Klinke</li>
<li>13x Kaltgeräte-Stecker (Mixer, Markbass, Blackstar, 3 Monitore, 4 PA, 1 Lampe, 1 Reserve)</li>
<li>2x Kaltgeräte-Verlängerung (zwischen Lampen)</li>
<li>4x DMX (3 Lampen, 1 Reserve)</li>
<li>...</li>
</ul>
<hr />
<h2>Finanzen</h2>
<p>... folgen in Kürze.</p>
{% endblock %} {% endblock %}
@@ -0,0 +1,18 @@
{% extends "gaehsnitz/base.html" %}
{% load static %}
{% block content %}
<h2>&#128736; Donnerstag 06.</h2>
<p>ganz viel Aufbau</p>
<h2>&#128736; Freitag 07.</h2>
<p>Warm-Up</p>
<h2>&#128736; Samstag 08.</h2>
<p>ganz viel Live-Mucke</p>
<h2>&#128736; Sonntag 09.</h2>
<p>ganz viel Abbau</p>
{% endblock %}
+5 -3
View File
@@ -1,9 +1,11 @@
from django.urls import path from django.urls import path
from gaehsnitz.views import NewsView, Archive2022View, Archive2024View from gaehsnitz.views import NewsView, AToZView, ProgramView, FinanceView, ForBandsView
urlpatterns = [ urlpatterns = [
path("", NewsView.as_view(), name="news"), path("", NewsView.as_view(), name="news"),
path("archive/2022", Archive2022View.as_view(), name="archive-2022"), path("atoz", AToZView.as_view(), name="atoz"),
path("archive/2024", Archive2024View.as_view(), name="archive-2024"), path("program", ProgramView.as_view(), name="program"),
path("finance", FinanceView.as_view(), name="finance"),
path("for-bands", ForBandsView.as_view(), name="for-bands"),
] ]
+18 -44
View File
@@ -14,17 +14,27 @@ class GaehsnitzTemplateView(TemplateView):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
delta_til_start = festival_start_date - date.today() delta_til_start = festival_start_date - date.today()
days_til_start = max(delta_til_start.days, 0) days_til_start = max(delta_til_start.days, 0)
context.update( context.update({
{
"days_til_festival_start": days_til_start, "days_til_festival_start": days_til_start,
} })
)
return context return context
class NewsView(GaehsnitzTemplateView): class NewsView(GaehsnitzTemplateView):
template_name = "gaehsnitz/news.html" template_name = "gaehsnitz/news.html"
class AToZView(GaehsnitzTemplateView):
template_name = "gaehsnitz/atoz.html"
class ProgramView(GaehsnitzTemplateView):
template_name = "gaehsnitz/program.html"
class FinanceView(GaehsnitzTemplateView):
template_name = "gaehsnitz/finance.html"
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
@@ -45,50 +55,14 @@ class NewsView(GaehsnitzTemplateView):
displayed_payments.append(Payment(purpose="Bands", amount=band_sum)) displayed_payments.append(Payment(purpose="Bands", amount=band_sum))
context.update( context.update({
{
"total_donations": total_donations, "total_donations": total_donations,
"total_payments": total_payments, "total_payments": total_payments,
"total_balance": total_balance, "total_balance": total_balance,
"payments": displayed_payments, "payments": displayed_payments,
} })
)
return context return context
class ForBandsView(GaehsnitzTemplateView):
class Archive2022View(GaehsnitzTemplateView): template_name = "gaehsnitz/for-bands.html"
template_name = "gaehsnitz/archive-2022.html"
class Archive2024View(GaehsnitzTemplateView):
template_name = "gaehsnitz/archive-2024.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
donations = Donation.objects.filter(date__year=2024)
payments = Payment.objects.filter(date__year=2024)
total_donations = donations.aggregate(sum=Sum("amount"))["sum"] or 0
total_payments = payments.aggregate(sum=Sum("amount"))["sum"] or 0
total_balance = total_donations - total_payments
band_sum, displayed_payments = 0, []
for pay in payments.order_by("date"):
if pay.purpose.startswith("Band"):
band_sum += pay.amount
else:
displayed_payments.append(pay)
displayed_payments.append(Payment(purpose="Bands", amount=band_sum))
context.update(
{
"total_donations": total_donations,
"total_payments": total_payments,
"total_balance": total_balance,
"payments": displayed_payments,
}
)
return context
+1 -1
View File
@@ -2,6 +2,6 @@ import os
from django.core.wsgi import get_wsgi_application from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gaehsnitzproject.settings") os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'gaehsnitzproject.settings')
application = get_wsgi_application() application = get_wsgi_application()
+2 -3
View File
@@ -1,12 +1,11 @@
#!/usr/bin/env python #!/usr/bin/env python
"""Django's command-line utility for administrative tasks.""" """Django's command-line utility for administrative tasks."""
import os import os
import sys import sys
def main(): def main():
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gaehsnitzproject.settings") os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'gaehsnitzproject.settings')
try: try:
from django.core.management import execute_from_command_line from django.core.management import execute_from_command_line
except ImportError as exc: except ImportError as exc:
@@ -18,5 +17,5 @@ def main():
execute_from_command_line(sys.argv) execute_from_command_line(sys.argv)
if __name__ == "__main__": if __name__ == '__main__':
main() main()
-21
View File
@@ -1,21 +0,0 @@
[project]
name = "gaehsnitz"
version = "0.1.0"
requires-python = ">=3.14"
dependencies = [
"django==6.0.5",
"gunicorn==25.3.0",
"psycopg[binary]==3.3.4",
]
[dependency-groups]
dev = [
"ruff==0.15.12",
]
[tool.ruff]
target-version = "py314"
line-length = 120
[tool.ruff.lint]
select = ["E", "F", "W", "I"]
+5 -2
View File
@@ -1,4 +1,7 @@
{ {
$schema: "https://docs.renovatebot.com/renovate-schema.json", "$schema": "https://docs.renovatebot.com/renovate-schema.json",
extends: ["config:recommended", ":configMigration"], "extends": [
"config:recommended",
":configMigration"
]
} }
+3
View File
@@ -0,0 +1,3 @@
django==6.0.1
gunicorn==24.0.0
psycopg[binary]==3.3.2