Compare commits
10 Commits
004fcb23ae
...
6c8ddbb4f0
| Author | SHA1 | Date | |
|---|---|---|---|
| 6c8ddbb4f0 | |||
| 24435660f5 | |||
|
|
0493c2c1db | ||
|
|
737a3c5335 | ||
|
|
a4c773a57d | ||
|
|
c1c6824364 | ||
|
|
b9544048e6 | ||
| f04d93c7f0 | |||
| ca3bf0f296 | |||
| efd0088124 |
@@ -1,22 +0,0 @@
|
|||||||
Vorname;Nachname;E-Mail;Telefon;IBAN;Straße;PLZ;Ort;Personentyp;Geburtsdatum;Pachtnummer;Pachtbeginn_Erste;Pachtende_Letzte;Pachtzins_Aktuell;Landwirtschaftliche_Ausbildung;Berufserfahrung_Jahre;Spezialisierung;Notizen;Aktiv
|
|
||||||
N/A;Groiner Milch KG;;;;Groiner Allee 18;46459;Rees;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
N/A;M u D Becker GbR;;;;Helweg 76;46348;Raesfeld;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Walter;Buchmann;;;;Büskes Heide 11;46499;Hamminkeln-Brünen;Herrn;;;;;;;;;;WAHR
|
|
||||||
Andreas;Elbers;;;;Grietherbusch Nr. 15;46459;Rees;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Fischer GbR;;;;Werricher Strasse 1;46487;Wesel;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Michael;Ingenbleek;;;;Achterhoeker Schulweg 39 a;47626;Kevelaer;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Bröcheler KG;;;;Kervenheimer Str. 30;47626;Kevelaer;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Jens;Bodden;;;;Moelscher Weg 16;47574;Goch;Herrn;;;;;;;;;;WAHR
|
|
||||||
Marcel;Müller;;;;Weysche Strasse 55;47546;Kalkar-Hanselaer;Herrn;;;;;;;;;;WAHR
|
|
||||||
Ludger;Paeßens;;;;Bergerfurther Strasse 4;46499;Hamminkeln;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Sander GbR;;;;Hardtbergweg 21;46569;Hünxe;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Dirk;Schmäh;;;;Schlümersweg 7 A;46499;Hamminkeln-Brünen;Herrn;;;;;;;;;;WAHR
|
|
||||||
Wolfgang;Schmitz;;;;Höst-Vornicker-Weg 1;47652;Weeze;Herrn;;;;;;;;;;WAHR
|
|
||||||
Sebastian;Scholten;;;;Underbergsheide 46;46485;Wesel-Obrighoven;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Ulmenhorst GbR;;;;Schlootweg 10;46499;Hamminkeln;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Simone;Gerten;;;;Obrighovener Str. 107;46485;Wesel;Frau;;;;;;;;;;WAHR
|
|
||||||
Günther;Engelmann;;;;Loher Weg 42;46484;Wesel;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Lühlshof KG;;;;Auf dem Heidchen 27;46485;Wesel;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Walter;Schmidt;;;;Ilserheider Str. 4;32469;Petershagen;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Inge und Tom Rose GbR;;;;Kohlbreite 22;34414;Warburg-Calenberg;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
N/A;Stiftung;;;;Schwarzensteiner Weg 75;46569;Hünxe;;;;;;;;;;;WAHR
|
|
||||||
|
|
Before Width: | Height: | Size: 207 KiB |
|
Before Width: | Height: | Size: 204 KiB |
|
Before Width: | Height: | Size: 207 KiB |
|
Before Width: | Height: | Size: 207 KiB |
@@ -1,22 +0,0 @@
|
|||||||
Vorname;Nachname;E-Mail;Telefon;IBAN;Straße;PLZ;Ort;Personentyp;Geburtsdatum;Pachtnummer;Pachtbeginn_Erste;Pachtende_Letzte;Pachtzins_Aktuell;Landwirtschaftliche_Ausbildung;Berufserfahrung_Jahre;Spezialisierung;Notizen;Aktiv
|
|
||||||
N/A;Groiner Milch KG;;;;Groiner Allee 18;46459;Rees;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
N/A;M u D Becker GbR;;;;Helweg 76;46348;Raesfeld;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Walter;Buchmann;;;;Büskes Heide 11;46499;Hamminkeln-Brünen;Herrn;;;;;;;;;;WAHR
|
|
||||||
Andreas;Elbers;;;;Grietherbusch Nr. 15;46459;Rees;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Fischer GbR;;;;Werricher Strasse 1;46487;Wesel;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Michael;Ingenbleek;;;;Achterhoeker Schulweg 39 a;47626;Kevelaer;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Bröcheler KG;;;;Kervenheimer Str. 30;47626;Kevelaer;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Jens;Bodden;;;;Moelscher Weg 16;47574;Goch;Herrn;;;;;;;;;;WAHR
|
|
||||||
Marcel;Müller;;;;Weysche Strasse 55;47546;Kalkar-Hanselaer;Herrn;;;;;;;;;;WAHR
|
|
||||||
Ludger;Paeßens;;;;Bergerfurther Strasse 4;46499;Hamminkeln;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Sander GbR;;;;Hardtbergweg 21;46569;Hünxe;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Dirk;Schmäh;;;;Schlümersweg 7 A;46499;Hamminkeln-Brünen;Herrn;;;;;;;;;;WAHR
|
|
||||||
Wolfgang;Schmitz;;;;Höst-Vornicker-Weg 1;47652;Weeze;Herrn;;;;;;;;;;WAHR
|
|
||||||
Sebastian;Scholten;;;;Underbergsheide 46;46485;Wesel-Obrighoven;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Ulmenhorst GbR;;;;Schlootweg 10;46499;Hamminkeln;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Simone;Gerten;;;;Obrighovener Str. 107;46485;Wesel;Frau;;;;;;;;;;WAHR
|
|
||||||
Günther;Engelmann;;;;Loher Weg 42;46484;Wesel;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Lühlshof KG;;;;Auf dem Heidchen 27;46485;Wesel;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Walter;Schmidt;;;;Ilserheider Str. 4;32469;Petershagen;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Inge und Tom Rose GbR;;;;Kohlbreite 22;34414;Warburg-Calenberg;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
N/A;Stiftung;;;;Schwarzensteiner Weg 75;46569;Hünxe;;;;;;;;;;;WAHR
|
|
||||||
|
|
Before Width: | Height: | Size: 207 KiB |
|
Before Width: | Height: | Size: 204 KiB |
|
Before Width: | Height: | Size: 207 KiB |
|
Before Width: | Height: | Size: 207 KiB |
@@ -1,22 +0,0 @@
|
|||||||
Vorname;Nachname;E-Mail;Telefon;IBAN;Straße;PLZ;Ort;Personentyp;Geburtsdatum;Pachtnummer;Pachtbeginn_Erste;Pachtende_Letzte;Pachtzins_Aktuell;Landwirtschaftliche_Ausbildung;Berufserfahrung_Jahre;Spezialisierung;Notizen;Aktiv
|
|
||||||
N/A;Groiner Milch KG;;;;Groiner Allee 18;46459;Rees;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
N/A;M u D Becker GbR;;;;Helweg 76;46348;Raesfeld;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Walter;Buchmann;;;;Büskes Heide 11;46499;Hamminkeln-Brünen;Herrn;;;;;;;;;;WAHR
|
|
||||||
Andreas;Elbers;;;;Grietherbusch Nr. 15;46459;Rees;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Fischer GbR;;;;Werricher Strasse 1;46487;Wesel;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Michael;Ingenbleek;;;;Achterhoeker Schulweg 39 a;47626;Kevelaer;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Bröcheler KG;;;;Kervenheimer Str. 30;47626;Kevelaer;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Jens;Bodden;;;;Moelscher Weg 16;47574;Goch;Herrn;;;;;;;;;;WAHR
|
|
||||||
Marcel;Müller;;;;Weysche Strasse 55;47546;Kalkar-Hanselaer;Herrn;;;;;;;;;;WAHR
|
|
||||||
Ludger;Paeßens;;;;Bergerfurther Strasse 4;46499;Hamminkeln;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Sander GbR;;;;Hardtbergweg 21;46569;Hünxe;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Dirk;Schmäh;;;;Schlümersweg 7 A;46499;Hamminkeln-Brünen;Herrn;;;;;;;;;;WAHR
|
|
||||||
Wolfgang;Schmitz;;;;Höst-Vornicker-Weg 1;47652;Weeze;Herrn;;;;;;;;;;WAHR
|
|
||||||
Sebastian;Scholten;;;;Underbergsheide 46;46485;Wesel-Obrighoven;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Ulmenhorst GbR;;;;Schlootweg 10;46499;Hamminkeln;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Simone;Gerten;;;;Obrighovener Str. 107;46485;Wesel;Frau;;;;;;;;;;WAHR
|
|
||||||
Günther;Engelmann;;;;Loher Weg 42;46484;Wesel;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Lühlshof KG;;;;Auf dem Heidchen 27;46485;Wesel;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Walter;Schmidt;;;;Ilserheider Str. 4;32469;Petershagen;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Inge und Tom Rose GbR;;;;Kohlbreite 22;34414;Warburg-Calenberg;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
N/A;Stiftung;;;;Schwarzensteiner Weg 75;46569;Hünxe;;;;;;;;;;;WAHR
|
|
||||||
|
|
Before Width: | Height: | Size: 207 KiB |
|
Before Width: | Height: | Size: 204 KiB |
|
Before Width: | Height: | Size: 207 KiB |
|
Before Width: | Height: | Size: 207 KiB |
@@ -1,22 +0,0 @@
|
|||||||
Vorname;Nachname;E-Mail;Telefon;IBAN;Straße;PLZ;Ort;Personentyp;Geburtsdatum;Pachtnummer;Pachtbeginn_Erste;Pachtende_Letzte;Pachtzins_Aktuell;Landwirtschaftliche_Ausbildung;Berufserfahrung_Jahre;Spezialisierung;Notizen;Aktiv
|
|
||||||
N/A;Groiner Milch KG;;;;Groiner Allee 18;46459;Rees;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
N/A;M u D Becker GbR;;;;Helweg 76;46348;Raesfeld;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Walter;Buchmann;;;;Büskes Heide 11;46499;Hamminkeln-Brünen;Herrn;;;;;;;;;;WAHR
|
|
||||||
Andreas;Elbers;;;;Grietherbusch Nr. 15;46459;Rees;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Fischer GbR;;;;Werricher Strasse 1;46487;Wesel;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Michael;Ingenbleek;;;;Achterhoeker Schulweg 39 a;47626;Kevelaer;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Bröcheler KG;;;;Kervenheimer Str. 30;47626;Kevelaer;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Jens;Bodden;;;;Moelscher Weg 16;47574;Goch;Herrn;;;;;;;;;;WAHR
|
|
||||||
Marcel;Müller;;;;Weysche Strasse 55;47546;Kalkar-Hanselaer;Herrn;;;;;;;;;;WAHR
|
|
||||||
Ludger;Paeßens;;;;Bergerfurther Strasse 4;46499;Hamminkeln;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Sander GbR;;;;Hardtbergweg 21;46569;Hünxe;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Dirk;Schmäh;;;;Schlümersweg 7 A;46499;Hamminkeln-Brünen;Herrn;;;;;;;;;;WAHR
|
|
||||||
Wolfgang;Schmitz;;;;Höst-Vornicker-Weg 1;47652;Weeze;Herrn;;;;;;;;;;WAHR
|
|
||||||
Sebastian;Scholten;;;;Underbergsheide 46;46485;Wesel-Obrighoven;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Ulmenhorst GbR;;;;Schlootweg 10;46499;Hamminkeln;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Simone;Gerten;;;;Obrighovener Str. 107;46485;Wesel;Frau;;;;;;;;;;WAHR
|
|
||||||
Günther;Engelmann;;;;Loher Weg 42;46484;Wesel;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Lühlshof KG;;;;Auf dem Heidchen 27;46485;Wesel;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Walter;Schmidt;;;;Ilserheider Str. 4;32469;Petershagen;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Inge und Tom Rose GbR;;;;Kohlbreite 22;34414;Warburg-Calenberg;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
N/A;Stiftung;;;;Schwarzensteiner Weg 75;46569;Hünxe;;;;;;;;;;;WAHR
|
|
||||||
|
@@ -1,22 +0,0 @@
|
|||||||
Vorname;Nachname;E-Mail;Telefon;IBAN;Straße;PLZ;Ort;Personentyp;Geburtsdatum;Pachtnummer;Pachtbeginn_Erste;Pachtende_Letzte;Pachtzins_Aktuell;Landwirtschaftliche_Ausbildung;Berufserfahrung_Jahre;Spezialisierung;Notizen;Aktiv
|
|
||||||
N/A;Groiner Milch KG;;;;Groiner Allee 18;46459;Rees;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
N/A;M u D Becker GbR;;;;Helweg 76;46348;Raesfeld;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Walter;Buchmann;;;;Büskes Heide 11;46499;Hamminkeln-Brünen;Herrn;;;;;;;;;;WAHR
|
|
||||||
Andreas;Elbers;;;;Grietherbusch Nr. 15;46459;Rees;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Fischer GbR;;;;Werricher Strasse 1;46487;Wesel;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Michael;Ingenbleek;;;;Achterhoeker Schulweg 39 a;47626;Kevelaer;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Bröcheler KG;;;;Kervenheimer Str. 30;47626;Kevelaer;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Jens;Bodden;;;;Moelscher Weg 16;47574;Goch;Herrn;;;;;;;;;;WAHR
|
|
||||||
Marcel;Müller;;;;Weysche Strasse 55;47546;Kalkar-Hanselaer;Herrn;;;;;;;;;;WAHR
|
|
||||||
Ludger;Paeßens;;;;Bergerfurther Strasse 4;46499;Hamminkeln;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Sander GbR;;;;Hardtbergweg 21;46569;Hünxe;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Dirk;Schmäh;;;;Schlümersweg 7 A;46499;Hamminkeln-Brünen;Herrn;;;;;;;;;;WAHR
|
|
||||||
Wolfgang;Schmitz;;;;Höst-Vornicker-Weg 1;47652;Weeze;Herrn;;;;;;;;;;WAHR
|
|
||||||
Sebastian;Scholten;;;;Underbergsheide 46;46485;Wesel-Obrighoven;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Ulmenhorst GbR;;;;Schlootweg 10;46499;Hamminkeln;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Simone;Gerten;;;;Obrighovener Str. 107;46485;Wesel;Frau;;;;;;;;;;WAHR
|
|
||||||
Günther;Engelmann;;;;Loher Weg 42;46484;Wesel;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Lühlshof KG;;;;Auf dem Heidchen 27;46485;Wesel;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Walter;Schmidt;;;;Ilserheider Str. 4;32469;Petershagen;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Inge und Tom Rose GbR;;;;Kohlbreite 22;34414;Warburg-Calenberg;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
N/A;Stiftung;;;;Schwarzensteiner Weg 75;46569;Hünxe;;;;;;;;;;;WAHR
|
|
||||||
|
@@ -1,22 +0,0 @@
|
|||||||
Vorname;Nachname;E-Mail;Telefon;IBAN;Straße;PLZ;Ort;Personentyp;Geburtsdatum;Pachtnummer;Pachtbeginn_Erste;Pachtende_Letzte;Pachtzins_Aktuell;Landwirtschaftliche_Ausbildung;Berufserfahrung_Jahre;Spezialisierung;Notizen;Aktiv
|
|
||||||
N/A;Groiner Milch KG;;;;Groiner Allee 18;46459;Rees;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
N/A;M u D Becker GbR;;;;Helweg 76;46348;Raesfeld;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Walter;Buchmann;;;;Büskes Heide 11;46499;Hamminkeln-Brünen;Herrn;;;;;;;;;;WAHR
|
|
||||||
Andreas;Elbers;;;;Grietherbusch Nr. 15;46459;Rees;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Fischer GbR;;;;Werricher Strasse 1;46487;Wesel;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Michael;Ingenbleek;;;;Achterhoeker Schulweg 39 a;47626;Kevelaer;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Bröcheler KG;;;;Kervenheimer Str. 30;47626;Kevelaer;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Jens;Bodden;;;;Moelscher Weg 16;47574;Goch;Herrn;;;;;;;;;;WAHR
|
|
||||||
Marcel;Müller;;;;Weysche Strasse 55;47546;Kalkar-Hanselaer;Herrn;;;;;;;;;;WAHR
|
|
||||||
Ludger;Paeßens;;;;Bergerfurther Strasse 4;46499;Hamminkeln;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Sander GbR;;;;Hardtbergweg 21;46569;Hünxe;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Dirk;Schmäh;;;;Schlümersweg 7 A;46499;Hamminkeln-Brünen;Herrn;;;;;;;;;;WAHR
|
|
||||||
Wolfgang;Schmitz;;;;Höst-Vornicker-Weg 1;47652;Weeze;Herrn;;;;;;;;;;WAHR
|
|
||||||
Sebastian;Scholten;;;;Underbergsheide 46;46485;Wesel-Obrighoven;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Ulmenhorst GbR;;;;Schlootweg 10;46499;Hamminkeln;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Simone;Gerten;;;;Obrighovener Str. 107;46485;Wesel;Frau;;;;;;;;;;WAHR
|
|
||||||
Günther;Engelmann;;;;Loher Weg 42;46484;Wesel;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Lühlshof KG;;;;Auf dem Heidchen 27;46485;Wesel;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Walter;Schmidt;;;;Ilserheider Str. 4;32469;Petershagen;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Inge und Tom Rose GbR;;;;Kohlbreite 22;34414;Warburg-Calenberg;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
N/A;Stiftung;;;;Schwarzensteiner Weg 75;46569;Hünxe;;;;;;;;;;;WAHR
|
|
||||||
|
@@ -1,22 +0,0 @@
|
|||||||
Vorname;Nachname;E-Mail;Telefon;IBAN;Straße;PLZ;Ort;Personentyp;Geburtsdatum;Pachtnummer;Pachtbeginn_Erste;Pachtende_Letzte;Pachtzins_Aktuell;Landwirtschaftliche_Ausbildung;Berufserfahrung_Jahre;Spezialisierung;Notizen;Aktiv
|
|
||||||
N/A;Groiner Milch KG;;;;Groiner Allee 18;46459;Rees;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
N/A;M u D Becker GbR;;;;Helweg 76;46348;Raesfeld;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Walter;Buchmann;;;;Büskes Heide 11;46499;Hamminkeln-Brünen;Herrn;;;;;;;;;;WAHR
|
|
||||||
Andreas;Elbers;;;;Grietherbusch Nr. 15;46459;Rees;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Fischer GbR;;;;Werricher Strasse 1;46487;Wesel;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Michael;Ingenbleek;;;;Achterhoeker Schulweg 39 a;47626;Kevelaer;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Bröcheler KG;;;;Kervenheimer Str. 30;47626;Kevelaer;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Jens;Bodden;;;;Moelscher Weg 16;47574;Goch;Herrn;;;;;;;;;;WAHR
|
|
||||||
Marcel;Müller;;;;Weysche Strasse 55;47546;Kalkar-Hanselaer;Herrn;;;;;;;;;;WAHR
|
|
||||||
Ludger;Paeßens;;;;Bergerfurther Strasse 4;46499;Hamminkeln;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Sander GbR;;;;Hardtbergweg 21;46569;Hünxe;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Dirk;Schmäh;;;;Schlümersweg 7 A;46499;Hamminkeln-Brünen;Herrn;;;;;;;;;;WAHR
|
|
||||||
Wolfgang;Schmitz;;;;Höst-Vornicker-Weg 1;47652;Weeze;Herrn;;;;;;;;;;WAHR
|
|
||||||
Sebastian;Scholten;;;;Underbergsheide 46;46485;Wesel-Obrighoven;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Ulmenhorst GbR;;;;Schlootweg 10;46499;Hamminkeln;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Simone;Gerten;;;;Obrighovener Str. 107;46485;Wesel;Frau;;;;;;;;;;WAHR
|
|
||||||
Günther;Engelmann;;;;Loher Weg 42;46484;Wesel;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Lühlshof KG;;;;Auf dem Heidchen 27;46485;Wesel;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Walter;Schmidt;;;;Ilserheider Str. 4;32469;Petershagen;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Inge und Tom Rose GbR;;;;Kohlbreite 22;34414;Warburg-Calenberg;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
N/A;Stiftung;;;;Schwarzensteiner Weg 75;46569;Hünxe;;;;;;;;;;;WAHR
|
|
||||||
|
|
Before Width: | Height: | Size: 207 KiB |
|
Before Width: | Height: | Size: 204 KiB |
|
Before Width: | Height: | Size: 207 KiB |
|
Before Width: | Height: | Size: 207 KiB |
@@ -1,22 +0,0 @@
|
|||||||
Vorname;Nachname;E-Mail;Telefon;IBAN;Straße;PLZ;Ort;Personentyp;Geburtsdatum;Pachtnummer;Pachtbeginn_Erste;Pachtende_Letzte;Pachtzins_Aktuell;Landwirtschaftliche_Ausbildung;Berufserfahrung_Jahre;Spezialisierung;Notizen;Aktiv
|
|
||||||
N/A;Groiner Milch KG;;;;Groiner Allee 18;46459;Rees;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
N/A;M u D Becker GbR;;;;Helweg 76;46348;Raesfeld;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Walter;Buchmann;;;;Büskes Heide 11;46499;Hamminkeln-Brünen;Herrn;;;;;;;;;;WAHR
|
|
||||||
Andreas;Elbers;;;;Grietherbusch Nr. 15;46459;Rees;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Fischer GbR;;;;Werricher Strasse 1;46487;Wesel;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Michael;Ingenbleek;;;;Achterhoeker Schulweg 39 a;47626;Kevelaer;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Bröcheler KG;;;;Kervenheimer Str. 30;47626;Kevelaer;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Jens;Bodden;;;;Moelscher Weg 16;47574;Goch;Herrn;;;;;;;;;;WAHR
|
|
||||||
Marcel;Müller;;;;Weysche Strasse 55;47546;Kalkar-Hanselaer;Herrn;;;;;;;;;;WAHR
|
|
||||||
Ludger;Paeßens;;;;Bergerfurther Strasse 4;46499;Hamminkeln;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Sander GbR;;;;Hardtbergweg 21;46569;Hünxe;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Dirk;Schmäh;;;;Schlümersweg 7 A;46499;Hamminkeln-Brünen;Herrn;;;;;;;;;;WAHR
|
|
||||||
Wolfgang;Schmitz;;;;Höst-Vornicker-Weg 1;47652;Weeze;Herrn;;;;;;;;;;WAHR
|
|
||||||
Sebastian;Scholten;;;;Underbergsheide 46;46485;Wesel-Obrighoven;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Ulmenhorst GbR;;;;Schlootweg 10;46499;Hamminkeln;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Simone;Gerten;;;;Obrighovener Str. 107;46485;Wesel;Frau;;;;;;;;;;WAHR
|
|
||||||
Günther;Engelmann;;;;Loher Weg 42;46484;Wesel;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Lühlshof KG;;;;Auf dem Heidchen 27;46485;Wesel;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Walter;Schmidt;;;;Ilserheider Str. 4;32469;Petershagen;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Inge und Tom Rose GbR;;;;Kohlbreite 22;34414;Warburg-Calenberg;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
N/A;Stiftung;;;;Schwarzensteiner Weg 75;46569;Hünxe;;;;;;;;;;;WAHR
|
|
||||||
|
|
Before Width: | Height: | Size: 207 KiB |
|
Before Width: | Height: | Size: 204 KiB |
|
Before Width: | Height: | Size: 207 KiB |
|
Before Width: | Height: | Size: 207 KiB |
@@ -1,22 +0,0 @@
|
|||||||
Vorname;Nachname;E-Mail;Telefon;IBAN;Straße;PLZ;Ort;Personentyp;Geburtsdatum;Pachtnummer;Pachtbeginn_Erste;Pachtende_Letzte;Pachtzins_Aktuell;Landwirtschaftliche_Ausbildung;Berufserfahrung_Jahre;Spezialisierung;Notizen;Aktiv
|
|
||||||
N/A;Groiner Milch KG;;;;Groiner Allee 18;46459;Rees;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
N/A;M u D Becker GbR;;;;Helweg 76;46348;Raesfeld;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Walter;Buchmann;;;;Büskes Heide 11;46499;Hamminkeln-Brünen;Herrn;;;;;;;;;;WAHR
|
|
||||||
Andreas;Elbers;;;;Grietherbusch Nr. 15;46459;Rees;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Fischer GbR;;;;Werricher Strasse 1;46487;Wesel;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Michael;Ingenbleek;;;;Achterhoeker Schulweg 39 a;47626;Kevelaer;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Bröcheler KG;;;;Kervenheimer Str. 30;47626;Kevelaer;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Jens;Bodden;;;;Moelscher Weg 16;47574;Goch;Herrn;;;;;;;;;;WAHR
|
|
||||||
Marcel;Müller;;;;Weysche Strasse 55;47546;Kalkar-Hanselaer;Herrn;;;;;;;;;;WAHR
|
|
||||||
Ludger;Paeßens;;;;Bergerfurther Strasse 4;46499;Hamminkeln;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Sander GbR;;;;Hardtbergweg 21;46569;Hünxe;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Dirk;Schmäh;;;;Schlümersweg 7 A;46499;Hamminkeln-Brünen;Herrn;;;;;;;;;;WAHR
|
|
||||||
Wolfgang;Schmitz;;;;Höst-Vornicker-Weg 1;47652;Weeze;Herrn;;;;;;;;;;WAHR
|
|
||||||
Sebastian;Scholten;;;;Underbergsheide 46;46485;Wesel-Obrighoven;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Ulmenhorst GbR;;;;Schlootweg 10;46499;Hamminkeln;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Simone;Gerten;;;;Obrighovener Str. 107;46485;Wesel;Frau;;;;;;;;;;WAHR
|
|
||||||
Günther;Engelmann;;;;Loher Weg 42;46484;Wesel;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Lühlshof KG;;;;Auf dem Heidchen 27;46485;Wesel;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
Walter;Schmidt;;;;Ilserheider Str. 4;32469;Petershagen;Herrn;;;;;;;;;;WAHR
|
|
||||||
N/A;Inge und Tom Rose GbR;;;;Kohlbreite 22;34414;Warburg-Calenberg;Gesellschaft;;;;;;;;;;WAHR
|
|
||||||
N/A;Stiftung;;;;Schwarzensteiner Weg 75;46569;Hünxe;;;;;;;;;;;WAHR
|
|
||||||
|
@@ -1,11 +0,0 @@
|
|||||||
# Static Files Directory
|
|
||||||
|
|
||||||
This directory contains static files for the Django application.
|
|
||||||
|
|
||||||
## Structure:
|
|
||||||
- `css/` - Custom CSS files
|
|
||||||
- `js/` - Custom JavaScript files
|
|
||||||
- `img/` - Image assets
|
|
||||||
- `fonts/` - Font files
|
|
||||||
|
|
||||||
Static files are collected to `staticfiles/` directory during deployment via `python manage.py collectstatic`.
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# Static Files Directory
|
|
||||||
|
|
||||||
This directory contains static files for the Django application.
|
|
||||||
|
|
||||||
## Structure:
|
|
||||||
- `css/` - Custom CSS files
|
|
||||||
- `js/` - Custom JavaScript files
|
|
||||||
- `img/` - Image assets
|
|
||||||
- `fonts/` - Font files
|
|
||||||
|
|
||||||
Static files are collected to `staticfiles/` directory during deployment via `python manage.py collectstatic`.
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# Static Files Directory
|
|
||||||
|
|
||||||
This directory contains static files for the Django application.
|
|
||||||
|
|
||||||
## Structure:
|
|
||||||
- `css/` - Custom CSS files
|
|
||||||
- `js/` - Custom JavaScript files
|
|
||||||
- `img/` - Image assets
|
|
||||||
- `fonts/` - Font files
|
|
||||||
|
|
||||||
Static files are collected to `staticfiles/` directory during deployment via `python manage.py collectstatic`.
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# Static Files Directory
|
|
||||||
|
|
||||||
This directory contains static files for the Django application.
|
|
||||||
|
|
||||||
## Structure:
|
|
||||||
- `css/` - Custom CSS files
|
|
||||||
- `js/` - Custom JavaScript files
|
|
||||||
- `img/` - Image assets
|
|
||||||
- `fonts/` - Font files
|
|
||||||
|
|
||||||
Static files are collected to `staticfiles/` directory during deployment via `python manage.py collectstatic`.
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# Static Files Directory
|
|
||||||
|
|
||||||
This directory contains static files for the Django application.
|
|
||||||
|
|
||||||
## Structure:
|
|
||||||
- `css/` - Custom CSS files
|
|
||||||
- `js/` - Custom JavaScript files
|
|
||||||
- `img/` - Image assets
|
|
||||||
- `fonts/` - Font files
|
|
||||||
|
|
||||||
Static files are collected to `staticfiles/` directory during deployment via `python manage.py collectstatic`.
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# Static Files Directory
|
|
||||||
|
|
||||||
This directory contains static files for the Django application.
|
|
||||||
|
|
||||||
## Structure:
|
|
||||||
- `css/` - Custom CSS files
|
|
||||||
- `js/` - Custom JavaScript files
|
|
||||||
- `img/` - Image assets
|
|
||||||
- `fonts/` - Font files
|
|
||||||
|
|
||||||
Static files are collected to `staticfiles/` directory during deployment via `python manage.py collectstatic`.
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# Static Files Directory
|
|
||||||
|
|
||||||
This directory contains static files for the Django application.
|
|
||||||
|
|
||||||
## Structure:
|
|
||||||
- `css/` - Custom CSS files
|
|
||||||
- `js/` - Custom JavaScript files
|
|
||||||
- `img/` - Image assets
|
|
||||||
- `fonts/` - Font files
|
|
||||||
|
|
||||||
Static files are collected to `staticfiles/` directory during deployment via `python manage.py collectstatic`.
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# Static Files Directory
|
|
||||||
|
|
||||||
This directory contains static files for the Django application.
|
|
||||||
|
|
||||||
## Structure:
|
|
||||||
- `css/` - Custom CSS files
|
|
||||||
- `js/` - Custom JavaScript files
|
|
||||||
- `img/` - Image assets
|
|
||||||
- `fonts/` - Font files
|
|
||||||
|
|
||||||
Static files are collected to `staticfiles/` directory during deployment via `python manage.py collectstatic`.
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# Static Files Directory
|
|
||||||
|
|
||||||
This directory contains static files for the Django application.
|
|
||||||
|
|
||||||
## Structure:
|
|
||||||
- `css/` - Custom CSS files
|
|
||||||
- `js/` - Custom JavaScript files
|
|
||||||
- `img/` - Image assets
|
|
||||||
- `fonts/` - Font files
|
|
||||||
|
|
||||||
Static files are collected to `staticfiles/` directory during deployment via `python manage.py collectstatic`.
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# Static Files Directory
|
|
||||||
|
|
||||||
This directory contains static files for the Django application.
|
|
||||||
|
|
||||||
## Structure:
|
|
||||||
- `css/` - Custom CSS files
|
|
||||||
- `js/` - Custom JavaScript files
|
|
||||||
- `img/` - Image assets
|
|
||||||
- `fonts/` - Font files
|
|
||||||
|
|
||||||
Static files are collected to `staticfiles/` directory during deployment via `python manage.py collectstatic`.
|
|
||||||
@@ -1349,6 +1349,9 @@ class UserPermissionForm(forms.Form):
|
|||||||
label = permission.name.lower()
|
label = permission.name.lower()
|
||||||
codename = permission.codename.lower()
|
codename = permission.codename.lower()
|
||||||
|
|
||||||
|
# Get bound field for proper template rendering
|
||||||
|
bound_field = self[field_name]
|
||||||
|
|
||||||
# More precise categorization based on both name and codename
|
# More precise categorization based on both name and codename
|
||||||
if (
|
if (
|
||||||
any(
|
any(
|
||||||
@@ -1365,7 +1368,7 @@ class UserPermissionForm(forms.Form):
|
|||||||
or "view_" in codename
|
or "view_" in codename
|
||||||
):
|
):
|
||||||
groups["entities"]["permissions"].append(
|
groups["entities"]["permissions"].append(
|
||||||
(field_name, field, permission)
|
(field_name, bound_field, permission)
|
||||||
)
|
)
|
||||||
elif (
|
elif (
|
||||||
any(
|
any(
|
||||||
@@ -1374,7 +1377,7 @@ class UserPermissionForm(forms.Form):
|
|||||||
or "dokument" in label
|
or "dokument" in label
|
||||||
):
|
):
|
||||||
groups["documents"]["permissions"].append(
|
groups["documents"]["permissions"].append(
|
||||||
(field_name, field, permission)
|
(field_name, bound_field, permission)
|
||||||
)
|
)
|
||||||
elif any(
|
elif any(
|
||||||
word in codename
|
word in codename
|
||||||
@@ -1394,7 +1397,7 @@ class UserPermissionForm(forms.Form):
|
|||||||
]
|
]
|
||||||
):
|
):
|
||||||
groups["financial"]["permissions"].append(
|
groups["financial"]["permissions"].append(
|
||||||
(field_name, field, permission)
|
(field_name, bound_field, permission)
|
||||||
)
|
)
|
||||||
elif any(
|
elif any(
|
||||||
word in codename
|
word in codename
|
||||||
@@ -1416,15 +1419,22 @@ class UserPermissionForm(forms.Form):
|
|||||||
]
|
]
|
||||||
):
|
):
|
||||||
groups["administration"]["permissions"].append(
|
groups["administration"]["permissions"].append(
|
||||||
(field_name, field, permission)
|
(field_name, bound_field, permission)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
groups["system"]["permissions"].append(
|
groups["system"]["permissions"].append(
|
||||||
(field_name, field, permission)
|
(field_name, bound_field, permission)
|
||||||
)
|
)
|
||||||
except Permission.DoesNotExist:
|
except Permission.DoesNotExist:
|
||||||
# Fallback for permissions that don't exist
|
# Create a fallback permission-like object with proper display
|
||||||
groups["system"]["permissions"].append((field_name, field, None))
|
class FallbackPermission:
|
||||||
|
def __init__(self, field_name):
|
||||||
|
self.name = field_name.replace('_', ' ').title()
|
||||||
|
self.codename = field_name
|
||||||
|
|
||||||
|
fallback_perm = FallbackPermission(field_name)
|
||||||
|
bound_field = self[field_name] # Get bound field for exception case too
|
||||||
|
groups["system"]["permissions"].append((field_name, bound_field, fallback_perm))
|
||||||
|
|
||||||
return groups
|
return groups
|
||||||
|
|
||||||
|
|||||||
84
app/stiftung/migrations/0042_add_separate_deadlines.py
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
# Generated migration for separate study proof and payment deadlines
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
from datetime import date
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_study_proof_deadline(jahr, quartal):
|
||||||
|
"""Calculate semester-based study proof deadline"""
|
||||||
|
# Q1, Q2 → March 15 (same year)
|
||||||
|
# Q3, Q4 → September 15 (same year)
|
||||||
|
if quartal in [1, 2]:
|
||||||
|
return date(jahr, 3, 15)
|
||||||
|
else: # Q3, Q4
|
||||||
|
return date(jahr, 9, 15)
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_payment_due_date(jahr, quartal):
|
||||||
|
"""Calculate quarterly payment due date (paid in advance)"""
|
||||||
|
# Q1 → December 15 (previous year)
|
||||||
|
# Q2 → March 15 (same year)
|
||||||
|
# Q3 → June 15 (same year)
|
||||||
|
# Q4 → September 15 (same year)
|
||||||
|
if quartal == 1:
|
||||||
|
return date(jahr - 1, 12, 15)
|
||||||
|
elif quartal == 2:
|
||||||
|
return date(jahr, 3, 15)
|
||||||
|
elif quartal == 3:
|
||||||
|
return date(jahr, 6, 15)
|
||||||
|
else: # Q4
|
||||||
|
return date(jahr, 9, 15)
|
||||||
|
|
||||||
|
|
||||||
|
def populate_deadlines(apps, schema_editor):
|
||||||
|
"""Populate new deadline fields for existing records"""
|
||||||
|
VierteljahresNachweis = apps.get_model('stiftung', 'VierteljahresNachweis')
|
||||||
|
|
||||||
|
for nachweis in VierteljahresNachweis.objects.all():
|
||||||
|
# Calculate and set study proof deadline
|
||||||
|
if not nachweis.studiennachweis_faelligkeitsdatum:
|
||||||
|
nachweis.studiennachweis_faelligkeitsdatum = calculate_study_proof_deadline(
|
||||||
|
nachweis.jahr, nachweis.quartal
|
||||||
|
)
|
||||||
|
|
||||||
|
# Calculate and set payment due date
|
||||||
|
if not nachweis.zahlung_faelligkeitsdatum:
|
||||||
|
nachweis.zahlung_faelligkeitsdatum = calculate_payment_due_date(
|
||||||
|
nachweis.jahr, nachweis.quartal
|
||||||
|
)
|
||||||
|
|
||||||
|
nachweis.save(update_fields=['studiennachweis_faelligkeitsdatum', 'zahlung_faelligkeitsdatum'])
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('stiftung', '0041_alter_geschichteseite_inhalt'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
# Add new fields
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='vierteljahresnachweis',
|
||||||
|
name='studiennachweis_faelligkeitsdatum',
|
||||||
|
field=models.DateField(
|
||||||
|
blank=True,
|
||||||
|
help_text='Semesterbasierte Frist: Q1/Q2 → 15. März, Q3/Q4 → 15. September',
|
||||||
|
null=True,
|
||||||
|
verbose_name='Studiennachweis Fälligkeitsdatum'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='vierteljahresnachweis',
|
||||||
|
name='zahlung_faelligkeitsdatum',
|
||||||
|
field=models.DateField(
|
||||||
|
blank=True,
|
||||||
|
help_text='Vierteljährliche Zahlungsfälligkeit im Voraus: Q1→15. Dez (Vorjahr), Q2→15. Mär, Q3→15. Jun, Q4→15. Sep',
|
||||||
|
null=True,
|
||||||
|
verbose_name='Zahlungsfälligkeit'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
# Populate existing records
|
||||||
|
migrations.RunPython(populate_deadlines, migrations.RunPython.noop),
|
||||||
|
]
|
||||||
|
|
||||||
@@ -2665,7 +2665,23 @@ class VierteljahresNachweis(models.Model):
|
|||||||
faelligkeitsdatum = models.DateField(
|
faelligkeitsdatum = models.DateField(
|
||||||
null=True,
|
null=True,
|
||||||
blank=True,
|
blank=True,
|
||||||
verbose_name="Fälligkeitsdatum"
|
verbose_name="Fälligkeitsdatum",
|
||||||
|
help_text="Veraltet - wird durch studiennachweis_faelligkeitsdatum und zahlung_faelligkeitsdatum ersetzt"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Separate deadlines for study proof (semester-based) and payment (quarterly)
|
||||||
|
studiennachweis_faelligkeitsdatum = models.DateField(
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
verbose_name="Studiennachweis Fälligkeitsdatum",
|
||||||
|
help_text="Semesterbasierte Frist: Q1/Q2 → 15. März, Q3/Q4 → 15. September"
|
||||||
|
)
|
||||||
|
|
||||||
|
zahlung_faelligkeitsdatum = models.DateField(
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
verbose_name="Zahlungsfälligkeit",
|
||||||
|
help_text="Vierteljährliche Zahlungsfälligkeit im Voraus: Q1→15. Dez (Vorjahr), Q2→15. Mär, Q3→15. Jun, Q4→15. Sep"
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@@ -2746,18 +2762,67 @@ class VierteljahresNachweis(models.Model):
|
|||||||
|
|
||||||
return int((completed_requirements / total_requirements) * 100) if total_requirements > 0 else 0
|
return int((completed_requirements / total_requirements) * 100) if total_requirements > 0 else 0
|
||||||
|
|
||||||
|
def get_study_proof_deadline(self):
|
||||||
|
"""Calculate semester-based study proof deadline"""
|
||||||
|
from datetime import date
|
||||||
|
# Q1, Q2 → March 15 (same year)
|
||||||
|
# Q3, Q4 → September 15 (same year)
|
||||||
|
if self.quartal in [1, 2]:
|
||||||
|
return date(self.jahr, 3, 15)
|
||||||
|
else: # Q3, Q4
|
||||||
|
return date(self.jahr, 9, 15)
|
||||||
|
|
||||||
|
def get_payment_due_date(self):
|
||||||
|
"""Calculate quarterly payment due date (paid in advance)"""
|
||||||
|
from datetime import date
|
||||||
|
# Q1 → December 15 (previous year)
|
||||||
|
# Q2 → March 15 (same year)
|
||||||
|
# Q3 → June 15 (same year)
|
||||||
|
# Q4 → September 15 (same year)
|
||||||
|
if self.quartal == 1:
|
||||||
|
return date(self.jahr - 1, 12, 15)
|
||||||
|
elif self.quartal == 2:
|
||||||
|
return date(self.jahr, 3, 15)
|
||||||
|
elif self.quartal == 3:
|
||||||
|
return date(self.jahr, 6, 15)
|
||||||
|
else: # Q4
|
||||||
|
return date(self.jahr, 9, 15)
|
||||||
|
|
||||||
|
def is_study_proof_overdue(self):
|
||||||
|
"""Check if study proof deadline has passed"""
|
||||||
|
if not self.studiennachweis_faelligkeitsdatum:
|
||||||
|
return False
|
||||||
|
from django.utils import timezone
|
||||||
|
return timezone.now().date() > self.studiennachweis_faelligkeitsdatum and not self.studiennachweis_eingereicht
|
||||||
|
|
||||||
|
def is_payment_overdue(self):
|
||||||
|
"""Check if payment due date has passed"""
|
||||||
|
if not self.zahlung_faelligkeitsdatum:
|
||||||
|
return False
|
||||||
|
from django.utils import timezone
|
||||||
|
# Payment is overdue if due date passed and no payment exists or payment is not completed
|
||||||
|
payment = self.get_related_support_payment()
|
||||||
|
if payment and payment.status in ['bezahlt', 'in_bearbeitung']:
|
||||||
|
return False
|
||||||
|
return timezone.now().date() > self.zahlung_faelligkeitsdatum
|
||||||
|
|
||||||
|
def is_overdue(self):
|
||||||
|
"""Check if either deadline has passed"""
|
||||||
|
return self.is_study_proof_overdue() or self.is_payment_overdue()
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
"""Override save to auto-update status and timestamps"""
|
"""Override save to auto-update status and timestamps"""
|
||||||
# Auto-set deadline if not provided (semester-based deadlines)
|
# Set study proof deadline (semester-based) if not provided
|
||||||
|
if not self.studiennachweis_faelligkeitsdatum:
|
||||||
|
self.studiennachweis_faelligkeitsdatum = self.get_study_proof_deadline()
|
||||||
|
|
||||||
|
# Set payment due date (quarterly, advance) if not provided
|
||||||
|
if not self.zahlung_faelligkeitsdatum:
|
||||||
|
self.zahlung_faelligkeitsdatum = self.get_payment_due_date()
|
||||||
|
|
||||||
|
# Backward compatibility: set faelligkeitsdatum from study proof deadline if not set
|
||||||
if not self.faelligkeitsdatum:
|
if not self.faelligkeitsdatum:
|
||||||
from datetime import date
|
self.faelligkeitsdatum = self.studiennachweis_faelligkeitsdatum
|
||||||
quarter_deadlines = {
|
|
||||||
1: date(self.jahr, 3, 15), # Q1 deadline: March 15 (Spring semester)
|
|
||||||
2: date(self.jahr, 3, 15), # Q2 deadline: March 15 (Spring semester, same as Q1)
|
|
||||||
3: date(self.jahr, 9, 15), # Q3 deadline: September 15 (Fall semester)
|
|
||||||
4: date(self.jahr, 9, 15), # Q4 deadline: September 15 (Fall semester, same as Q3)
|
|
||||||
}
|
|
||||||
self.faelligkeitsdatum = quarter_deadlines.get(self.quartal)
|
|
||||||
|
|
||||||
# Auto-update status based on completion
|
# Auto-update status based on completion
|
||||||
if self.is_complete():
|
if self.is_complete():
|
||||||
@@ -2773,18 +2838,71 @@ class VierteljahresNachweis(models.Model):
|
|||||||
|
|
||||||
def get_related_support_payment(self):
|
def get_related_support_payment(self):
|
||||||
"""Get the related support payment for this quarterly confirmation"""
|
"""Get the related support payment for this quarterly confirmation"""
|
||||||
from datetime import datetime
|
from datetime import date, timedelta
|
||||||
|
from django.db.models import Q
|
||||||
|
|
||||||
quarter_start = datetime(self.jahr, (self.quartal - 1) * 3 + 1, 1).date()
|
# Use payment due date from quarterly confirmation for accurate search
|
||||||
quarter_end = datetime(self.jahr, self.quartal * 3, 1).date()
|
# This is more accurate than using quarter date range, especially for Q1 (Dec 15 prev year)
|
||||||
|
payment_due_date = self.zahlung_faelligkeitsdatum
|
||||||
|
if not payment_due_date:
|
||||||
|
# Fallback: calculate if not set
|
||||||
|
if self.quartal == 1:
|
||||||
|
payment_due_date = date(self.jahr - 1, 12, 15)
|
||||||
|
elif self.quartal == 2:
|
||||||
|
payment_due_date = date(self.jahr, 3, 15)
|
||||||
|
elif self.quartal == 3:
|
||||||
|
payment_due_date = date(self.jahr, 6, 15)
|
||||||
|
else: # Q4
|
||||||
|
payment_due_date = date(self.jahr, 9, 15)
|
||||||
|
|
||||||
|
# Search for existing payment - match by payment due date and description
|
||||||
|
# Use a date range around the due date (±30 days) to catch any variations
|
||||||
|
date_start = payment_due_date - timedelta(days=30)
|
||||||
|
date_end = payment_due_date + timedelta(days=30)
|
||||||
|
|
||||||
return DestinataerUnterstuetzung.objects.filter(
|
return DestinataerUnterstuetzung.objects.filter(
|
||||||
destinataer=self.destinataer,
|
destinataer=self.destinataer,
|
||||||
faellig_am__gte=quarter_start,
|
faellig_am__gte=date_start,
|
||||||
faellig_am__lt=quarter_end,
|
faellig_am__lte=date_end
|
||||||
beschreibung__contains=f"Q{self.quartal}/{self.jahr}"
|
).filter(
|
||||||
|
Q(beschreibung__contains=f"Q{self.quartal}/{self.jahr}") |
|
||||||
|
Q(beschreibung__contains=f"Vierteljährliche Unterstützung Q{self.quartal}/{self.jahr}")
|
||||||
).first()
|
).first()
|
||||||
|
|
||||||
|
def auto_approve_next_quarter(self):
|
||||||
|
"""Auto-approve the next quarter when Q1 or Q3 is approved (semester-based logic)"""
|
||||||
|
if self.quartal in [1, 3] and self.status == "geprueft":
|
||||||
|
next_quarter = self.quartal + 1
|
||||||
|
try:
|
||||||
|
next_nachweis = VierteljahresNachweis.objects.get(
|
||||||
|
destinataer=self.destinataer,
|
||||||
|
jahr=self.jahr,
|
||||||
|
quartal=next_quarter
|
||||||
|
)
|
||||||
|
|
||||||
|
if next_nachweis.status in ["offen", "teilweise"]:
|
||||||
|
# Copy study proof confirmations from current quarter (semester-based)
|
||||||
|
next_nachweis.studiennachweis_eingereicht = self.studiennachweis_eingereicht
|
||||||
|
next_nachweis.studiennachweis_datei = self.studiennachweis_datei
|
||||||
|
next_nachweis.studiennachweis_bemerkung = self.studiennachweis_bemerkung
|
||||||
|
|
||||||
|
# Set study proof deadline for next quarter (same semester)
|
||||||
|
next_nachweis.studiennachweis_faelligkeitsdatum = next_nachweis.get_study_proof_deadline()
|
||||||
|
|
||||||
|
# Set auto-approved status
|
||||||
|
next_nachweis.status = "auto_geprueft"
|
||||||
|
next_nachweis.geprueft_am = timezone.now()
|
||||||
|
next_nachweis.geprueft_von = self.geprueft_von
|
||||||
|
next_nachweis.save(update_fields=[
|
||||||
|
'studiennachweis_eingereicht', 'studiennachweis_datei', 'studiennachweis_bemerkung',
|
||||||
|
'studiennachweis_faelligkeitsdatum', 'status', 'geprueft_am', 'geprueft_von'
|
||||||
|
])
|
||||||
|
|
||||||
|
return next_nachweis
|
||||||
|
except VierteljahresNachweis.DoesNotExist:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_or_create_for_period(cls, destinataer, jahr, quartal):
|
def get_or_create_for_period(cls, destinataer, jahr, quartal):
|
||||||
"""Get or create a quarterly confirmation for a specific period"""
|
"""Get or create a quarterly confirmation for a specific period"""
|
||||||
|
|||||||
@@ -219,6 +219,11 @@ urlpatterns = [
|
|||||||
views.verwaltungskosten_edit,
|
views.verwaltungskosten_edit,
|
||||||
name="verwaltungskosten_edit",
|
name="verwaltungskosten_edit",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"geschaeftsfuehrung/verwaltungskosten/<uuid:pk>/loeschen/",
|
||||||
|
views.verwaltungskosten_delete,
|
||||||
|
name="verwaltungskosten_delete",
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"verwaltungskosten/mark-paid/",
|
"verwaltungskosten/mark-paid/",
|
||||||
views.mark_expense_paid,
|
views.mark_expense_paid,
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ from .forms import (DestinataerForm, DestinataerNotizForm,
|
|||||||
FoerderungForm, LandForm, PaechterForm, PersonForm,
|
FoerderungForm, LandForm, PaechterForm, PersonForm,
|
||||||
UnterstuetzungForm, UnterstuetzungMarkAsPaidForm, VierteljahresNachweisForm)
|
UnterstuetzungForm, UnterstuetzungMarkAsPaidForm, VierteljahresNachweisForm)
|
||||||
|
|
||||||
|
@login_required
|
||||||
def home(request):
|
def home(request):
|
||||||
"""Home page for the Stiftungsverwaltung application"""
|
"""Home page for the Stiftungsverwaltung application"""
|
||||||
from stiftung.services.calendar_service import StiftungsKalenderService
|
from stiftung.services.calendar_service import StiftungsKalenderService
|
||||||
@@ -4203,6 +4203,42 @@ def verwaltungskosten_edit(request, pk):
|
|||||||
return render(request, "stiftung/verwaltungskosten_form.html", context)
|
return render(request, "stiftung/verwaltungskosten_form.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def verwaltungskosten_delete(request, pk):
|
||||||
|
"""Lösche Verwaltungskosten"""
|
||||||
|
from stiftung.models import Verwaltungskosten
|
||||||
|
|
||||||
|
verwaltungskosten = get_object_or_404(Verwaltungskosten, pk=pk)
|
||||||
|
|
||||||
|
if request.method == "POST":
|
||||||
|
bezeichnung = verwaltungskosten.bezeichnung
|
||||||
|
|
||||||
|
# Log the deletion
|
||||||
|
from stiftung.audit import log_action
|
||||||
|
log_action(
|
||||||
|
request=request,
|
||||||
|
action="delete",
|
||||||
|
entity_type="verwaltungskosten",
|
||||||
|
entity_id=str(verwaltungskosten.pk),
|
||||||
|
entity_name=bezeichnung,
|
||||||
|
description=f'Verwaltungskosten "{bezeichnung}" wurden gelöscht',
|
||||||
|
)
|
||||||
|
|
||||||
|
verwaltungskosten.delete()
|
||||||
|
messages.success(
|
||||||
|
request,
|
||||||
|
f'Verwaltungskosten "{bezeichnung}" wurden erfolgreich gelöscht.',
|
||||||
|
)
|
||||||
|
return redirect("stiftung:verwaltungskosten_list")
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"verwaltungskosten": verwaltungskosten,
|
||||||
|
"title": f"Verwaltungskosten löschen: {verwaltungskosten.bezeichnung}",
|
||||||
|
}
|
||||||
|
|
||||||
|
return render(request, "stiftung/verwaltungskosten_delete.html", context)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def mark_expense_paid(request):
|
def mark_expense_paid(request):
|
||||||
"""Markiere eine Ausgabe als bezahlt"""
|
"""Markiere eine Ausgabe als bezahlt"""
|
||||||
@@ -7386,21 +7422,33 @@ def create_quarterly_support_payment(nachweis):
|
|||||||
if not destinataer.iban:
|
if not destinataer.iban:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Calculate quarter date range for more robust search
|
# Search for existing payment using payment due date from quarterly confirmation
|
||||||
quarter_start = datetime(nachweis.jahr, (nachweis.quartal - 1) * 3 + 1, 1).date()
|
# This is more accurate than using quarter date range, especially for Q1 (Dec 15 prev year)
|
||||||
if nachweis.quartal == 4: # Q4 special case
|
payment_due_date = nachweis.zahlung_faelligkeitsdatum
|
||||||
quarter_end = datetime(nachweis.jahr + 1, 1, 1).date()
|
if not payment_due_date:
|
||||||
else:
|
# Fallback: calculate if not set
|
||||||
quarter_end = datetime(nachweis.jahr, nachweis.quartal * 3 + 1, 1).date()
|
if nachweis.quartal == 1:
|
||||||
|
payment_due_date = date(nachweis.jahr - 1, 12, 15)
|
||||||
|
elif nachweis.quartal == 2:
|
||||||
|
payment_due_date = date(nachweis.jahr, 3, 15)
|
||||||
|
elif nachweis.quartal == 3:
|
||||||
|
payment_due_date = date(nachweis.jahr, 6, 15)
|
||||||
|
else: # Q4
|
||||||
|
payment_due_date = date(nachweis.jahr, 9, 15)
|
||||||
|
|
||||||
|
# Search for existing payment - match by payment due date and description
|
||||||
|
# Use a date range around the due date (±30 days) to catch any variations
|
||||||
|
from datetime import timedelta
|
||||||
|
date_start = payment_due_date - timedelta(days=30)
|
||||||
|
date_end = payment_due_date + timedelta(days=30)
|
||||||
|
|
||||||
# Search for existing payment - use broader criteria to catch all possibilities
|
|
||||||
existing_payment = DestinataerUnterstuetzung.objects.filter(
|
existing_payment = DestinataerUnterstuetzung.objects.filter(
|
||||||
destinataer=destinataer,
|
destinataer=destinataer,
|
||||||
faellig_am__gte=quarter_start,
|
faellig_am__gte=date_start,
|
||||||
faellig_am__lt=quarter_end
|
faellig_am__lte=date_end
|
||||||
).filter(
|
).filter(
|
||||||
Q(beschreibung__contains=f"Q{nachweis.quartal}/{nachweis.jahr}") |
|
Q(beschreibung__contains=f"Q{nachweis.quartal}/{nachweis.jahr}") |
|
||||||
Q(beschreibung__contains=f"Vierteljährliche Unterstützung")
|
Q(beschreibung__contains=f"Vierteljährliche Unterstützung Q{nachweis.quartal}/{nachweis.jahr}")
|
||||||
).first()
|
).first()
|
||||||
|
|
||||||
if existing_payment:
|
if existing_payment:
|
||||||
@@ -7421,9 +7469,11 @@ def create_quarterly_support_payment(nachweis):
|
|||||||
if not default_konto:
|
if not default_konto:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Calculate payment due date (advance payments 3 months before quarter)
|
# Use payment due date from quarterly confirmation (already calculated by model)
|
||||||
# Q1: December 15 (previous year), Q2: March 15, Q3: June 15, Q4: September 15
|
# This ensures consistency with zahlung_faelligkeitsdatum
|
||||||
|
payment_due_date = nachweis.zahlung_faelligkeitsdatum
|
||||||
|
if not payment_due_date:
|
||||||
|
# Fallback: calculate if not set (should not happen, but safety check)
|
||||||
if nachweis.quartal == 1: # Q1 payment due December 15 of previous year
|
if nachweis.quartal == 1: # Q1 payment due December 15 of previous year
|
||||||
payment_due_date = date(nachweis.jahr - 1, 12, 15)
|
payment_due_date = date(nachweis.jahr - 1, 12, 15)
|
||||||
elif nachweis.quartal == 2: # Q2 payment due March 15
|
elif nachweis.quartal == 2: # Q2 payment due March 15
|
||||||
@@ -7454,9 +7504,14 @@ def create_quarterly_support_payment(nachweis):
|
|||||||
@login_required
|
@login_required
|
||||||
def quarterly_confirmation_create(request, destinataer_id):
|
def quarterly_confirmation_create(request, destinataer_id):
|
||||||
"""Create a new quarterly confirmation for a destinataer"""
|
"""Create a new quarterly confirmation for a destinataer"""
|
||||||
|
import logging
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
logger.info(f"quarterly_confirmation_create called: method={request.method}, destinataer_id={destinataer_id}")
|
||||||
|
|
||||||
destinataer = get_object_or_404(Destinataer, pk=destinataer_id)
|
destinataer = get_object_or_404(Destinataer, pk=destinataer_id)
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
|
logger.info(f"POST data: {request.POST}")
|
||||||
jahr = request.POST.get('jahr')
|
jahr = request.POST.get('jahr')
|
||||||
quartal = request.POST.get('quartal')
|
quartal = request.POST.get('quartal')
|
||||||
|
|
||||||
@@ -7479,25 +7534,40 @@ def quarterly_confirmation_create(request, destinataer_id):
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# Create new quarterly confirmation
|
# Create new quarterly confirmation
|
||||||
|
try:
|
||||||
nachweis = VierteljahresNachweis.objects.create(
|
nachweis = VierteljahresNachweis.objects.create(
|
||||||
destinataer=destinataer,
|
destinataer=destinataer,
|
||||||
jahr=jahr,
|
jahr=jahr,
|
||||||
quartal=quartal,
|
quartal=quartal,
|
||||||
studiennachweis_erforderlich=True, # Always required now
|
studiennachweis_erforderlich=True, # Always required now
|
||||||
)
|
)
|
||||||
|
# Deadlines are automatically set by the model's save() method
|
||||||
|
# studiennachweis_faelligkeitsdatum: semester-based (Q1/Q2→Mar 15, Q3/Q4→Sep 15)
|
||||||
|
# zahlung_faelligkeitsdatum: quarterly advance (Q1→Dec 15 prev year, Q2→Mar 15, Q3→Jun 15, Q4→Sep 15)
|
||||||
|
|
||||||
# Set deadline (15th of second month of quarter)
|
# Refresh from database to ensure deadlines are set
|
||||||
deadline_months = {1: 5, 2: 8, 3: 11, 4: 2} # Q1->May, Q2->Aug, Q3->Nov, Q4->Feb(next year)
|
nachweis.refresh_from_db()
|
||||||
deadline_month = deadline_months[quartal]
|
|
||||||
deadline_year = jahr if quartal != 4 else jahr + 1
|
|
||||||
|
|
||||||
from datetime import date
|
studiennachweis_str = nachweis.studiennachweis_faelligkeitsdatum.strftime('%d.%m.%Y') if nachweis.studiennachweis_faelligkeitsdatum else "Nicht gesetzt"
|
||||||
nachweis.faelligkeitsdatum = date(deadline_year, deadline_month, 15)
|
zahlung_str = nachweis.zahlung_faelligkeitsdatum.strftime('%d.%m.%Y') if nachweis.zahlung_faelligkeitsdatum else "Nicht gesetzt"
|
||||||
nachweis.save()
|
|
||||||
|
|
||||||
messages.success(
|
messages.success(
|
||||||
request,
|
request,
|
||||||
f"Quartal {jahr} Q{quartal} wurde erfolgreich für {destinataer.get_full_name()} erstellt."
|
f"Quartal {jahr} Q{quartal} wurde erfolgreich für {destinataer.get_full_name()} erstellt. "
|
||||||
|
f"Studiennachweis fällig: {studiennachweis_str}, "
|
||||||
|
f"Zahlung fällig: {zahlung_str}."
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
from django.db import IntegrityError
|
||||||
|
if isinstance(e, IntegrityError):
|
||||||
|
messages.error(
|
||||||
|
request,
|
||||||
|
f"Quartal {jahr} Q{quartal} existiert bereits für {destinataer.get_full_name()}."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
messages.error(
|
||||||
|
request,
|
||||||
|
f"Fehler beim Erstellen des Quartals: {str(e)}"
|
||||||
)
|
)
|
||||||
|
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
@@ -7619,14 +7689,25 @@ def quarterly_confirmation_approve(request, pk):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Handle support payment - create if missing, update if exists
|
# Handle support payment - create if missing, update if exists
|
||||||
if not related_payment:
|
# Check if payment already exists before calling create_quarterly_support_payment()
|
||||||
# Create new support payment
|
payment_existed_before = related_payment is not None
|
||||||
|
|
||||||
|
# Use create_quarterly_support_payment() which handles both cases (find existing or create new)
|
||||||
related_payment = create_quarterly_support_payment(nachweis)
|
related_payment = create_quarterly_support_payment(nachweis)
|
||||||
if related_payment:
|
if related_payment:
|
||||||
|
# Update status to 'in_bearbeitung' for both new and existing payments
|
||||||
|
old_status = related_payment.status
|
||||||
related_payment.status = 'in_bearbeitung'
|
related_payment.status = 'in_bearbeitung'
|
||||||
related_payment.aktualisiert_am = timezone.now()
|
related_payment.aktualisiert_am = timezone.now()
|
||||||
related_payment.save()
|
related_payment.save()
|
||||||
|
|
||||||
|
if payment_existed_before:
|
||||||
|
messages.success(
|
||||||
|
request,
|
||||||
|
f"Vierteljahresnachweis freigegeben und bestehende Unterstützung für {nachweis.destinataer.get_full_name()} "
|
||||||
|
f"({nachweis.jahr} Q{nachweis.quartal}) wurde von '{old_status}' auf 'in Bearbeitung' aktualisiert."
|
||||||
|
)
|
||||||
|
else:
|
||||||
messages.success(
|
messages.success(
|
||||||
request,
|
request,
|
||||||
f"Vierteljahresnachweis freigegeben und neue Unterstützung über {related_payment.betrag}€ für {nachweis.destinataer.get_full_name()} "
|
f"Vierteljahresnachweis freigegeben und neue Unterstützung über {related_payment.betrag}€ für {nachweis.destinataer.get_full_name()} "
|
||||||
@@ -7638,23 +7719,6 @@ def quarterly_confirmation_approve(request, pk):
|
|||||||
f"Vierteljahresnachweis freigegeben, aber Unterstützung konnte nicht erstellt werden. "
|
f"Vierteljahresnachweis freigegeben, aber Unterstützung konnte nicht erstellt werden. "
|
||||||
f"Bitte prüfen Sie die Einstellungen für {nachweis.destinataer.get_full_name()}."
|
f"Bitte prüfen Sie die Einstellungen für {nachweis.destinataer.get_full_name()}."
|
||||||
)
|
)
|
||||||
elif related_payment.status == 'geplant':
|
|
||||||
# Update existing payment
|
|
||||||
related_payment.status = 'in_bearbeitung'
|
|
||||||
related_payment.aktualisiert_am = timezone.now()
|
|
||||||
related_payment.save()
|
|
||||||
|
|
||||||
messages.success(
|
|
||||||
request,
|
|
||||||
f"Vierteljahresnachweis und zugehörige Unterstützung für {nachweis.destinataer.get_full_name()} "
|
|
||||||
f"({nachweis.jahr} Q{nachweis.quartal}) wurden freigegeben."
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
messages.success(
|
|
||||||
request,
|
|
||||||
f"Vierteljahresnachweis für {nachweis.destinataer.get_full_name()} "
|
|
||||||
f"({nachweis.jahr} Q{nachweis.quartal}) wurde freigegeben."
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
messages.error(
|
messages.error(
|
||||||
request,
|
request,
|
||||||
|
|||||||
@@ -727,8 +727,8 @@
|
|||||||
<span>© 2025 van Hees-Theyssen-Vogel'sche Stiftung. Alle Rechte vorbehalten.</span>
|
<span>© 2025 van Hees-Theyssen-Vogel'sche Stiftung. Alle Rechte vorbehalten.</span>
|
||||||
<br>
|
<br>
|
||||||
<small class="text-muted">
|
<small class="text-muted">
|
||||||
<i class="fas fa-leaf text-success"></i> v2.1.4 - Enhanced Destinataer Management • Sept 2025
|
<i class="fas fa-leaf text-success"></i> v3.0.0 - Calendar Integration & Payment System • Okt 2025
|
||||||
<span class="badge badge-primary ml-2">🚀 Enhanced</span>
|
<span class="badge badge-success ml-2">✨ Major Release</span>
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -466,7 +466,7 @@
|
|||||||
<i class="fas fa-calendar-check me-2"></i>Vierteljährliche Nachweise
|
<i class="fas fa-calendar-check me-2"></i>Vierteljährliche Nachweise
|
||||||
</h5>
|
</h5>
|
||||||
<div>
|
<div>
|
||||||
<small class="text-light me-3">Frist: jeweils 15. des zweiten Quartalsmonats</small>
|
<small class="text-light me-3">Studiennachweis: 15. März / 15. September | Zahlung: vierteljährlich im Voraus</small>
|
||||||
<button type="button" class="btn btn-sm btn-light"
|
<button type="button" class="btn btn-sm btn-light"
|
||||||
data-bs-toggle="modal"
|
data-bs-toggle="modal"
|
||||||
data-bs-target="#addQuarterModal"
|
data-bs-target="#addQuarterModal"
|
||||||
@@ -478,32 +478,76 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
{% if quarterly_confirmations %}
|
{% if quarterly_confirmations %}
|
||||||
|
<style>
|
||||||
|
.quarterly-table {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
table-layout: auto;
|
||||||
|
}
|
||||||
|
.quarterly-table th {
|
||||||
|
white-space: nowrap;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.6rem 0.5rem;
|
||||||
|
}
|
||||||
|
.quarterly-table td {
|
||||||
|
padding: 0.6rem 0.5rem;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.quarterly-table .col-zeitraum {
|
||||||
|
width: 85px;
|
||||||
|
}
|
||||||
|
.quarterly-table .col-status {
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
.quarterly-table .col-fortschritt {
|
||||||
|
width: 70px;
|
||||||
|
}
|
||||||
|
.quarterly-table .col-fristen {
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
.quarterly-table .col-check {
|
||||||
|
width: 40px;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0.6rem 0.3rem;
|
||||||
|
}
|
||||||
|
.quarterly-table .col-aktionen {
|
||||||
|
width: 110px;
|
||||||
|
}
|
||||||
|
.quarterly-table .progress {
|
||||||
|
height: 18px;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.quarterly-table .badge {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
padding: 0.3em 0.5em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-hover">
|
<table class="table table-hover table-sm quarterly-table">
|
||||||
<thead class="table-light">
|
<thead class="table-light">
|
||||||
<tr>
|
<tr>
|
||||||
<th>Zeitraum</th>
|
<th class="col-zeitraum">Zeitraum</th>
|
||||||
<th>Status</th>
|
<th class="col-status">Status</th>
|
||||||
<th>Fortschritt</th>
|
<th class="col-fortschritt">Fortschritt</th>
|
||||||
<th>Fälligkeit</th>
|
<th class="col-fristen">Fristen</th>
|
||||||
<th>Studiennachweis</th>
|
<th class="col-check" title="Studiennachweis"><i class="fas fa-graduation-cap"></i></th>
|
||||||
<th>Einkommen</th>
|
<th class="col-check" title="Einkommen"><i class="fas fa-euro-sign"></i></th>
|
||||||
<th>Vermögen</th>
|
<th class="col-check" title="Vermögen"><i class="fas fa-piggy-bank"></i></th>
|
||||||
<th>Aktionen</th>
|
<th class="col-aktionen">Aktionen</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for nachweis in quarterly_confirmations %}
|
{% for nachweis in quarterly_confirmations %}
|
||||||
<tr {% if nachweis.is_overdue %}class="table-warning"{% endif %}>
|
<tr {% if nachweis.is_overdue %}class="table-warning"{% endif %}>
|
||||||
<td>
|
<td class="col-zeitraum">
|
||||||
<strong>{{ nachweis.jahr }} {{ nachweis.get_quarter_display|truncatechars:3 }}</strong>
|
<strong>{{ nachweis.jahr }} Q{{ nachweis.quartal }}</strong>
|
||||||
{% if nachweis.is_overdue %}
|
{% if nachweis.is_overdue %}
|
||||||
<br><small class="text-danger"><i class="fas fa-exclamation-triangle"></i> Überfällig</small>
|
<br><small class="text-danger"><i class="fas fa-exclamation-triangle"></i></small>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td class="col-status">
|
||||||
{% if nachweis.status == 'offen' %}
|
{% if nachweis.status == 'offen' %}
|
||||||
<span class="badge bg-secondary">Ausstehend</span>
|
<span class="badge bg-secondary">Offen</span>
|
||||||
{% elif nachweis.status == 'teilweise' %}
|
{% elif nachweis.status == 'teilweise' %}
|
||||||
<span class="badge bg-warning">Teilweise</span>
|
<span class="badge bg-warning">Teilweise</span>
|
||||||
{% elif nachweis.status == 'eingereicht' %}
|
{% elif nachweis.status == 'eingereicht' %}
|
||||||
@@ -511,8 +555,8 @@
|
|||||||
{% elif nachweis.status == 'geprueft' %}
|
{% elif nachweis.status == 'geprueft' %}
|
||||||
<span class="badge bg-success">Freigegeben</span>
|
<span class="badge bg-success">Freigegeben</span>
|
||||||
{% elif nachweis.status == 'auto_geprueft' %}
|
{% elif nachweis.status == 'auto_geprueft' %}
|
||||||
<span class="badge bg-success">
|
<span class="badge bg-success" title="Auto-Freigabe">
|
||||||
<i class="fas fa-magic me-1"></i>Auto-Freigabe
|
<i class="fas fa-magic"></i> Auto
|
||||||
</span>
|
</span>
|
||||||
{% elif nachweis.status == 'nachbesserung' %}
|
{% elif nachweis.status == 'nachbesserung' %}
|
||||||
<span class="badge bg-warning">Nachbesserung</span>
|
<span class="badge bg-warning">Nachbesserung</span>
|
||||||
@@ -520,9 +564,9 @@
|
|||||||
<span class="badge bg-danger">Abgelehnt</span>
|
<span class="badge bg-danger">Abgelehnt</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td class="col-fortschritt">
|
||||||
{% with completion=nachweis.get_completion_percentage %}
|
{% with completion=nachweis.get_completion_percentage %}
|
||||||
<div class="progress" style="height: 20px;">
|
<div class="progress" title="{{ completion }}%">
|
||||||
<div class="progress-bar
|
<div class="progress-bar
|
||||||
{% if completion == 100 %}bg-success
|
{% if completion == 100 %}bg-success
|
||||||
{% elif completion >= 70 %}bg-info
|
{% elif completion >= 70 %}bg-info
|
||||||
@@ -539,14 +583,33 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td class="col-fristen">
|
||||||
{% if nachweis.faelligkeitsdatum %}
|
<div class="small" style="line-height: 1.4;">
|
||||||
<small>{{ nachweis.faelligkeitsdatum|date:"d.m.Y" }}</small>
|
{% if nachweis.studiennachweis_faelligkeitsdatum %}
|
||||||
{% else %}
|
<div class="mb-1">
|
||||||
<small class="text-muted">Nicht festgelegt</small>
|
<i class="fas fa-graduation-cap text-primary" title="Studiennachweis"></i>
|
||||||
|
<span class="{% if nachweis.is_study_proof_overdue %}text-danger fw-bold{% endif %}">
|
||||||
|
{{ nachweis.studiennachweis_faelligkeitsdatum|date:"d.m.Y" }}
|
||||||
|
</span>
|
||||||
|
{% if nachweis.is_study_proof_overdue %}
|
||||||
|
<i class="fas fa-exclamation-triangle text-danger" title="Überfällig"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if nachweis.zahlung_faelligkeitsdatum %}
|
||||||
|
<div>
|
||||||
|
<i class="fas fa-euro-sign text-success" title="Zahlung"></i>
|
||||||
|
<span class="{% if nachweis.is_payment_overdue %}text-danger fw-bold{% endif %}">
|
||||||
|
{{ nachweis.zahlung_faelligkeitsdatum|date:"d.m.Y" }}
|
||||||
|
</span>
|
||||||
|
{% if nachweis.is_payment_overdue %}
|
||||||
|
<i class="fas fa-exclamation-triangle text-danger" title="Überfällig"></i>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center">
|
<td class="col-check">
|
||||||
{% if nachweis.studiennachweis_eingereicht %}
|
{% if nachweis.studiennachweis_eingereicht %}
|
||||||
{% if nachweis.studiennachweis_datei %}
|
{% if nachweis.studiennachweis_datei %}
|
||||||
<a href="{{ nachweis.studiennachweis_datei.url }}" target="_blank" class="text-success" title="Datei ansehen">
|
<a href="{{ nachweis.studiennachweis_datei.url }}" target="_blank" class="text-success" title="Datei ansehen">
|
||||||
@@ -555,13 +618,13 @@
|
|||||||
{% elif nachweis.studiennachweis_bemerkung %}
|
{% elif nachweis.studiennachweis_bemerkung %}
|
||||||
<i class="fas fa-comment text-info" title="Bemerkung vorhanden"></i>
|
<i class="fas fa-comment text-info" title="Bemerkung vorhanden"></i>
|
||||||
{% else %}
|
{% else %}
|
||||||
<i class="fas fa-check text-success"></i>
|
<i class="fas fa-check text-success" title="Vorhanden"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<i class="fas fa-times text-muted"></i>
|
<i class="fas fa-times text-muted" title="Nicht vorhanden"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center">
|
<td class="col-check">
|
||||||
{% if nachweis.einkommenssituation_bestaetigt %}
|
{% if nachweis.einkommenssituation_bestaetigt %}
|
||||||
{% if nachweis.einkommenssituation_datei %}
|
{% if nachweis.einkommenssituation_datei %}
|
||||||
<a href="{{ nachweis.einkommenssituation_datei.url }}" target="_blank" class="text-success" title="Datei ansehen">
|
<a href="{{ nachweis.einkommenssituation_datei.url }}" target="_blank" class="text-success" title="Datei ansehen">
|
||||||
@@ -570,13 +633,13 @@
|
|||||||
{% elif nachweis.einkommenssituation_text %}
|
{% elif nachweis.einkommenssituation_text %}
|
||||||
<i class="fas fa-comment text-info" title="{{ nachweis.einkommenssituation_text|truncatechars:50 }}"></i>
|
<i class="fas fa-comment text-info" title="{{ nachweis.einkommenssituation_text|truncatechars:50 }}"></i>
|
||||||
{% else %}
|
{% else %}
|
||||||
<i class="fas fa-check text-success"></i>
|
<i class="fas fa-check text-success" title="Vorhanden"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<i class="fas fa-times text-muted"></i>
|
<i class="fas fa-times text-muted" title="Nicht vorhanden"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center">
|
<td class="col-check">
|
||||||
{% if nachweis.vermogenssituation_bestaetigt %}
|
{% if nachweis.vermogenssituation_bestaetigt %}
|
||||||
{% if nachweis.vermogenssituation_datei %}
|
{% if nachweis.vermogenssituation_datei %}
|
||||||
<a href="{{ nachweis.vermogenssituation_datei.url }}" target="_blank" class="text-success" title="Datei ansehen">
|
<a href="{{ nachweis.vermogenssituation_datei.url }}" target="_blank" class="text-success" title="Datei ansehen">
|
||||||
@@ -585,38 +648,38 @@
|
|||||||
{% elif nachweis.vermogenssituation_text %}
|
{% elif nachweis.vermogenssituation_text %}
|
||||||
<i class="fas fa-comment text-info" title="{{ nachweis.vermogenssituation_text|truncatechars:50 }}"></i>
|
<i class="fas fa-comment text-info" title="{{ nachweis.vermogenssituation_text|truncatechars:50 }}"></i>
|
||||||
{% else %}
|
{% else %}
|
||||||
<i class="fas fa-check text-success"></i>
|
<i class="fas fa-check text-success" title="Vorhanden"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<i class="fas fa-times text-muted"></i>
|
<i class="fas fa-times text-muted" title="Nicht vorhanden"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td class="col-aktionen">
|
||||||
<div class="btn-group" role="group" aria-label="Aktionen">
|
<div class="btn-group btn-group-sm" role="group" aria-label="Aktionen">
|
||||||
<a href="{% url 'stiftung:quarterly_confirmation_edit' nachweis.id %}"
|
<a href="{% url 'stiftung:quarterly_confirmation_edit' nachweis.id %}"
|
||||||
class="btn btn-sm btn-outline-primary"
|
class="btn btn-outline-primary btn-sm"
|
||||||
title="Bearbeiten">
|
title="Bearbeiten">
|
||||||
<i class="fas fa-edit"></i>
|
<i class="fas fa-edit"></i>
|
||||||
</a>
|
</a>
|
||||||
{% if user.is_staff %}
|
{% if user.is_staff %}
|
||||||
{% if nachweis.status == 'eingereicht' %}
|
{% if nachweis.status == 'eingereicht' %}
|
||||||
<button type="button"
|
<button type="button"
|
||||||
class="btn btn-sm btn-outline-success"
|
class="btn btn-outline-success btn-sm"
|
||||||
onclick="approveQuarterly('{{ nachweis.id }}')"
|
onclick="approveQuarterly('{{ nachweis.id }}')"
|
||||||
title="Freigeben">
|
title="Freigeben">
|
||||||
<i class="fas fa-check"></i>
|
<i class="fas fa-check"></i>
|
||||||
</button>
|
</button>
|
||||||
{% elif nachweis.status == 'geprueft' %}
|
{% elif nachweis.status == 'geprueft' %}
|
||||||
<button type="button"
|
<button type="button"
|
||||||
class="btn btn-sm btn-outline-success"
|
class="btn btn-outline-success btn-sm"
|
||||||
onclick="approveQuarterly('{{ nachweis.id }}')"
|
onclick="approveQuarterly('{{ nachweis.id }}')"
|
||||||
title="Erneut freigeben / Unterstützung synchronisieren">
|
title="Erneut freigeben">
|
||||||
<i class="fas fa-sync"></i>
|
<i class="fas fa-sync"></i>
|
||||||
</button>
|
</button>
|
||||||
<button type="button"
|
<button type="button"
|
||||||
class="btn btn-sm btn-outline-warning"
|
class="btn btn-outline-warning btn-sm"
|
||||||
onclick="resetQuarterly('{{ nachweis.id }}')"
|
onclick="resetQuarterly('{{ nachweis.id }}')"
|
||||||
title="Status zurücksetzen">
|
title="Zurücksetzen">
|
||||||
<i class="fas fa-undo"></i>
|
<i class="fas fa-undo"></i>
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -630,7 +693,40 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!-- Add Quarter Modal -->
|
|
||||||
|
{% else %}
|
||||||
|
<div class="text-center py-4">
|
||||||
|
<i class="fas fa-calendar-check fa-3x text-muted mb-3"></i>
|
||||||
|
<h5 class="text-muted">Keine vierteljährlichen Nachweise vorhanden</h5>
|
||||||
|
<p class="text-muted">Klicken Sie auf "Quartal hinzufügen", um einen neuen Nachweis zu erstellen.</p>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Notes Section -->
|
||||||
|
<div class="card shadow mb-4">
|
||||||
|
<div class="card-header bg-secondary text-white">
|
||||||
|
<h5 class="card-title mb-0">
|
||||||
|
<i class="fas fa-sticky-note me-2"></i>Notizen
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="mb-0">
|
||||||
|
<span class="view-mode">
|
||||||
|
{% if destinataer.notizen %}
|
||||||
|
{{ destinataer.notizen|linebreaks }}
|
||||||
|
{% else %}
|
||||||
|
<em class="text-muted">Keine Notizen vorhanden</em>
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
<textarea name="notizen" class="form-control edit-mode" style="display: none;" rows="4" placeholder="Notizen und Bemerkungen">{{ destinataer.notizen }}</textarea>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<!-- Add Quarter Modal (außerhalb des edit-form) -->
|
||||||
<div class="modal fade" id="addQuarterModal" tabindex="-1" aria-labelledby="addQuarterModalLabel" aria-hidden="true">
|
<div class="modal fade" id="addQuarterModal" tabindex="-1" aria-labelledby="addQuarterModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
@@ -640,7 +736,7 @@
|
|||||||
</h5>
|
</h5>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Schließen"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Schließen"></button>
|
||||||
</div>
|
</div>
|
||||||
<form method="post" action="{% url 'stiftung:quarterly_confirmation_create' destinataer.pk %}">
|
<form method="post" action="{% url 'stiftung:quarterly_confirmation_create' destinataer.pk %}" id="addQuarterForm">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -683,38 +779,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% else %}
|
|
||||||
<div class="text-center py-4">
|
|
||||||
<i class="fas fa-calendar-check fa-3x text-muted mb-3"></i>
|
|
||||||
<h5 class="text-muted">Keine vierteljährlichen Nachweise vorhanden</h5>
|
|
||||||
<p class="text-muted">Klicken Sie auf "Quartal hinzufügen", um einen neuen Nachweis zu erstellen.</p>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Notes Section -->
|
|
||||||
<div class="card shadow mb-4">
|
|
||||||
<div class="card-header bg-secondary text-white">
|
|
||||||
<h5 class="card-title mb-0">
|
|
||||||
<i class="fas fa-sticky-note me-2"></i>Notizen
|
|
||||||
</h5>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="mb-0">
|
|
||||||
<span class="view-mode">
|
|
||||||
{% if destinataer.notizen %}
|
|
||||||
{{ destinataer.notizen|linebreaks }}
|
|
||||||
{% else %}
|
|
||||||
<em class="text-muted">Keine Notizen vorhanden</em>
|
|
||||||
{% endif %}
|
|
||||||
</span>
|
|
||||||
<textarea name="notizen" class="form-control edit-mode" style="display: none;" rows="4" placeholder="Notizen und Bemerkungen">{{ destinataer.notizen }}</textarea>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<!-- Förderungen -->
|
<!-- Förderungen -->
|
||||||
{% if foerderungen %}
|
{% if foerderungen %}
|
||||||
<div class="card shadow mb-4">
|
<div class="card shadow mb-4">
|
||||||
@@ -1268,5 +1332,25 @@ function resetQuarterly(nachweisId) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle add quarter form submission using event delegation
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
// Use event delegation to catch form submission
|
||||||
|
document.addEventListener('submit', function(e) {
|
||||||
|
const form = e.target;
|
||||||
|
if (form && form.id === 'addQuarterForm') {
|
||||||
|
console.log('Add quarter form submitted');
|
||||||
|
console.log('Form action:', form.action);
|
||||||
|
|
||||||
|
// Form will submit normally, page will reload after redirect
|
||||||
|
// Modal will be closed automatically when page reloads
|
||||||
|
const submitBtn = form.querySelector('button[type="submit"]');
|
||||||
|
if (submitBtn) {
|
||||||
|
submitBtn.disabled = true;
|
||||||
|
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Wird erstellt...';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -155,8 +155,15 @@
|
|||||||
{% endif %}">
|
{% endif %}">
|
||||||
{{ nachweis.get_status_display }}
|
{{ nachweis.get_status_display }}
|
||||||
</span>
|
</span>
|
||||||
{% if nachweis.faelligkeitsdatum %}
|
{% if nachweis.studiennachweis_faelligkeitsdatum or nachweis.zahlung_faelligkeitsdatum %}
|
||||||
<br><small class="opacity-75">Fällig: {{ nachweis.faelligkeitsdatum|date:"d.m.Y" }}</small>
|
<br><small class="opacity-75">
|
||||||
|
{% if nachweis.studiennachweis_faelligkeitsdatum %}
|
||||||
|
Studiennachweis: {{ nachweis.studiennachweis_faelligkeitsdatum|date:"d.m.Y" }}
|
||||||
|
{% endif %}
|
||||||
|
{% if nachweis.zahlung_faelligkeitsdatum %}
|
||||||
|
| Zahlung: {{ nachweis.zahlung_faelligkeitsdatum|date:"d.m.Y" }}
|
||||||
|
{% endif %}
|
||||||
|
</small>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -175,8 +182,25 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<p class="mb-2"><strong>Zeitraum:</strong> {{ nachweis.jahr }} {{ nachweis.get_quarter_display }}</p>
|
<p class="mb-2"><strong>Zeitraum:</strong> {{ nachweis.jahr }} {{ nachweis.get_quarter_display }}</p>
|
||||||
{% if nachweis.faelligkeitsdatum %}
|
{% if nachweis.studiennachweis_faelligkeitsdatum %}
|
||||||
<p class="mb-0"><strong>Fälligkeitsdatum:</strong> {{ nachweis.faelligkeitsdatum|date:"d.m.Y" }}</p>
|
<p class="mb-1"><strong>Studiennachweis fällig:</strong>
|
||||||
|
<span class="{% if nachweis.is_study_proof_overdue %}text-danger{% endif %}">
|
||||||
|
{{ nachweis.studiennachweis_faelligkeitsdatum|date:"d.m.Y" }}
|
||||||
|
</span>
|
||||||
|
{% if nachweis.is_study_proof_overdue %}
|
||||||
|
<i class="fas fa-exclamation-triangle text-danger" title="Überfällig"></i>
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
{% if nachweis.zahlung_faelligkeitsdatum %}
|
||||||
|
<p class="mb-0"><strong>Zahlung fällig:</strong>
|
||||||
|
<span class="{% if nachweis.is_payment_overdue %}text-danger{% endif %}">
|
||||||
|
{{ nachweis.zahlung_faelligkeitsdatum|date:"d.m.Y" }}
|
||||||
|
</span>
|
||||||
|
{% if nachweis.is_payment_overdue %}
|
||||||
|
<i class="fas fa-exclamation-triangle text-danger" title="Überfällig"></i>
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -420,8 +444,25 @@
|
|||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{% if nachweis.faelligkeitsdatum %}
|
{% if nachweis.studiennachweis_faelligkeitsdatum %}
|
||||||
<p class="mb-2"><strong>Fälligkeit:</strong> {{ nachweis.faelligkeitsdatum|date:"d.m.Y" }}</p>
|
<p class="mb-1"><strong>Studiennachweis fällig:</strong>
|
||||||
|
<span class="{% if nachweis.is_study_proof_overdue %}text-danger{% endif %}">
|
||||||
|
{{ nachweis.studiennachweis_faelligkeitsdatum|date:"d.m.Y" }}
|
||||||
|
</span>
|
||||||
|
{% if nachweis.is_study_proof_overdue %}
|
||||||
|
<i class="fas fa-exclamation-triangle text-danger" title="Überfällig"></i>
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
{% if nachweis.zahlung_faelligkeitsdatum %}
|
||||||
|
<p class="mb-2"><strong>Zahlung fällig:</strong>
|
||||||
|
<span class="{% if nachweis.is_payment_overdue %}text-danger{% endif %}">
|
||||||
|
{{ nachweis.zahlung_faelligkeitsdatum|date:"d.m.Y" }}
|
||||||
|
</span>
|
||||||
|
{% if nachweis.is_payment_overdue %}
|
||||||
|
<i class="fas fa-exclamation-triangle text-danger" title="Überfällig"></i>
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if nachweis.eingereicht_am %}
|
{% if nachweis.eingereicht_am %}
|
||||||
|
|||||||
92
app/templates/stiftung/verwaltungskosten_delete.html
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block title %}Verwaltungskosten löschen - van Hees-Theyssen-Vogel'sche Stiftung{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="d-sm-flex align-items-center justify-content-between mb-4">
|
||||||
|
<h1 class="h3 mb-0 text-gray-800">
|
||||||
|
<i class="fas fa-trash me-2"></i>Verwaltungskosten löschen
|
||||||
|
</h1>
|
||||||
|
<a href="{% url 'stiftung:verwaltungskosten_list' %}" class="btn btn-outline-secondary">
|
||||||
|
<i class="fas fa-arrow-left me-1"></i>Zurück zur Liste
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-8 mx-auto">
|
||||||
|
<div class="card shadow">
|
||||||
|
<div class="card-header py-3 bg-danger">
|
||||||
|
<h6 class="m-0 font-weight-bold text-white">
|
||||||
|
<i class="fas fa-exclamation-triangle me-2"></i>Löschen bestätigen
|
||||||
|
</h6>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="alert alert-warning">
|
||||||
|
<strong>Achtung!</strong> Diese Aktion kann nicht rückgängig gemacht werden.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="mb-4">
|
||||||
|
Sind Sie sicher, dass Sie die folgenden Verwaltungskosten löschen möchten?
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-bordered">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Bezeichnung:</strong></td>
|
||||||
|
<td>{{ verwaltungskosten.bezeichnung }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Datum:</strong></td>
|
||||||
|
<td>{{ verwaltungskosten.datum|date:"d.m.Y" }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Betrag:</strong></td>
|
||||||
|
<td><strong>€{{ verwaltungskosten.betrag|floatformat:2 }}</strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Kategorie:</strong></td>
|
||||||
|
<td>{{ verwaltungskosten.get_kategorie_display }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Status:</strong></td>
|
||||||
|
<td>
|
||||||
|
<span class="badge bg-{{ verwaltungskosten.get_status_color }}">
|
||||||
|
{{ verwaltungskosten.get_status_display }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% if verwaltungskosten.lieferant_firma %}
|
||||||
|
<tr>
|
||||||
|
<td><strong>Lieferant/Firma:</strong></td>
|
||||||
|
<td>{{ verwaltungskosten.lieferant_firma }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
{% if verwaltungskosten.rechnungsnummer %}
|
||||||
|
<tr>
|
||||||
|
<td><strong>Rechnungsnummer:</strong></td>
|
||||||
|
<td>{{ verwaltungskosten.rechnungsnummer }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="post" class="d-flex gap-2 justify-content-end">
|
||||||
|
{% csrf_token %}
|
||||||
|
<a href="{% url 'stiftung:verwaltungskosten_list' %}" class="btn btn-secondary">
|
||||||
|
<i class="fas fa-times me-1"></i>Abbrechen
|
||||||
|
</a>
|
||||||
|
<button type="submit" class="btn btn-danger">
|
||||||
|
<i class="fas fa-trash me-1"></i>Endgültig löschen
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@@ -138,13 +138,10 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="btn-group btn-group-sm" role="group">
|
<div class="btn-group btn-group-sm" role="group">
|
||||||
<a href="#" class="btn btn-outline-primary" title="Bearbeiten">
|
<a href="{% url 'stiftung:verwaltungskosten_edit' kosten.pk %}" class="btn btn-outline-primary" title="Bearbeiten">
|
||||||
<i class="fas fa-edit"></i>
|
<i class="fas fa-edit"></i>
|
||||||
</a>
|
</a>
|
||||||
<a href="#" class="btn btn-outline-info" title="Details">
|
<a href="{% url 'stiftung:verwaltungskosten_delete' kosten.pk %}" class="btn btn-outline-danger" title="Löschen">
|
||||||
<i class="fas fa-eye"></i>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="btn btn-outline-danger" title="Löschen">
|
|
||||||
<i class="fas fa-trash"></i>
|
<i class="fas fa-trash"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -47,8 +47,11 @@ services:
|
|||||||
- PAPERLESS_DESTINATAERE_TAG_ID=1
|
- PAPERLESS_DESTINATAERE_TAG_ID=1
|
||||||
- PAPERLESS_LAND_TAG_ID=3
|
- PAPERLESS_LAND_TAG_ID=3
|
||||||
- PAPERLESS_ADMIN_TAG_ID=2
|
- PAPERLESS_ADMIN_TAG_ID=2
|
||||||
|
- GRAMPS_URL=http://grampsweb:5000
|
||||||
|
- GRAMPS_USERNAME=admin@localhost
|
||||||
|
- GRAMPS_PASSWORD=gramps_dev_password
|
||||||
ports:
|
ports:
|
||||||
- "8081:8000"
|
- "18081:8000"
|
||||||
volumes:
|
volumes:
|
||||||
- ./app:/app
|
- ./app:/app
|
||||||
command: ["python", "manage.py", "runserver", "0.0.0.0:8000"]
|
command: ["python", "manage.py", "runserver", "0.0.0.0:8000"]
|
||||||
@@ -80,9 +83,31 @@ services:
|
|||||||
- db
|
- db
|
||||||
- redis
|
- redis
|
||||||
|
|
||||||
|
grampsweb:
|
||||||
|
image: ghcr.io/gramps-project/grampsweb:latest
|
||||||
|
ports:
|
||||||
|
- "18090:5000"
|
||||||
|
environment:
|
||||||
|
- GRAMPSWEB_SECRET_KEY=dev-grampsweb-secret-key-not-for-production
|
||||||
|
- GRAMPSWEB_ADMIN_EMAIL=admin@localhost
|
||||||
|
- GRAMPSWEB_ADMIN_PASSWORD=gramps_dev_password
|
||||||
|
- GRAMPSWEB_TREE=Stiftung
|
||||||
|
- GRAMPSWEB_BASE_URL=/ahnenforschung
|
||||||
|
- GRAMPSWEB_STATIC_PATH=/ahnenforschung/static
|
||||||
|
- GRAMPSWEB_STATIC_URL=/ahnenforschung/static/
|
||||||
|
- GRAMPSWEB_CELERY_CONFIG__broker_url=redis://redis:6379/0
|
||||||
|
- GRAMPSWEB_CELERY_CONFIG__result_backend=redis://redis:6379/0
|
||||||
|
- GRAMPSWEB_RATELIMIT_STORAGE_URI=redis://redis:6379/1
|
||||||
|
- GRAMPSWEB_NEW_DB_BACKEND=sqlite
|
||||||
|
volumes:
|
||||||
|
- gramps_data_dev:/app/data
|
||||||
|
depends_on:
|
||||||
|
- redis
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
dbdata_dev:
|
dbdata_dev:
|
||||||
paperless_data_dev:
|
paperless_data_dev:
|
||||||
paperless_media_dev:
|
paperless_media_dev:
|
||||||
paperless_export_dev:
|
paperless_export_dev:
|
||||||
paperless_consume_dev:
|
paperless_consume_dev:
|
||||||
|
gramps_data_dev:
|
||||||
|
|||||||
16
compose.yml
@@ -53,6 +53,10 @@ services:
|
|||||||
- PAPERLESS_DESTINATAERE_TAG_ID=${PAPERLESS_DESTINATAERE_TAG_ID}
|
- PAPERLESS_DESTINATAERE_TAG_ID=${PAPERLESS_DESTINATAERE_TAG_ID}
|
||||||
- PAPERLESS_LAND_TAG_ID=${PAPERLESS_LAND_TAG_ID}
|
- PAPERLESS_LAND_TAG_ID=${PAPERLESS_LAND_TAG_ID}
|
||||||
- PAPERLESS_ADMIN_TAG_ID=${PAPERLESS_ADMIN_TAG_ID}
|
- PAPERLESS_ADMIN_TAG_ID=${PAPERLESS_ADMIN_TAG_ID}
|
||||||
|
- GRAMPS_URL=${GRAMPS_URL}
|
||||||
|
- GRAMPS_USERNAME=${GRAMPS_USERNAME}
|
||||||
|
- GRAMPS_PASSWORD=${GRAMPS_PASSWORD}
|
||||||
|
- GRAMPS_API_TOKEN=${GRAMPS_API_TOKEN}
|
||||||
ports:
|
ports:
|
||||||
- "8081:8000"
|
- "8081:8000"
|
||||||
volumes:
|
volumes:
|
||||||
@@ -70,6 +74,10 @@ services:
|
|||||||
- DJANGO_SECRET_KEY=${DJANGO_SECRET_KEY}
|
- DJANGO_SECRET_KEY=${DJANGO_SECRET_KEY}
|
||||||
- DJANGO_DEBUG=${DJANGO_DEBUG}
|
- DJANGO_DEBUG=${DJANGO_DEBUG}
|
||||||
- REDIS_URL=${REDIS_URL}
|
- REDIS_URL=${REDIS_URL}
|
||||||
|
- GRAMPS_URL=${GRAMPS_URL}
|
||||||
|
- GRAMPS_USERNAME=${GRAMPS_USERNAME}
|
||||||
|
- GRAMPS_PASSWORD=${GRAMPS_PASSWORD}
|
||||||
|
- GRAMPS_API_TOKEN=${GRAMPS_API_TOKEN}
|
||||||
depends_on:
|
depends_on:
|
||||||
- redis
|
- redis
|
||||||
- db
|
- db
|
||||||
@@ -86,6 +94,10 @@ services:
|
|||||||
- DJANGO_SECRET_KEY=${DJANGO_SECRET_KEY}
|
- DJANGO_SECRET_KEY=${DJANGO_SECRET_KEY}
|
||||||
- DJANGO_DEBUG=${DJANGO_DEBUG}
|
- DJANGO_DEBUG=${DJANGO_DEBUG}
|
||||||
- REDIS_URL=${REDIS_URL}
|
- REDIS_URL=${REDIS_URL}
|
||||||
|
- GRAMPS_URL=${GRAMPS_URL}
|
||||||
|
- GRAMPS_USERNAME=${GRAMPS_USERNAME}
|
||||||
|
- GRAMPS_PASSWORD=${GRAMPS_PASSWORD}
|
||||||
|
- GRAMPS_API_TOKEN=${GRAMPS_API_TOKEN}
|
||||||
depends_on:
|
depends_on:
|
||||||
- redis
|
- redis
|
||||||
- db
|
- db
|
||||||
@@ -100,7 +112,9 @@ services:
|
|||||||
- GRAMPSWEB_ADMIN_EMAIL=${GRAMPSWEB_ADMIN_EMAIL}
|
- GRAMPSWEB_ADMIN_EMAIL=${GRAMPSWEB_ADMIN_EMAIL}
|
||||||
- GRAMPSWEB_ADMIN_PASSWORD=${GRAMPSWEB_ADMIN_PASSWORD}
|
- GRAMPSWEB_ADMIN_PASSWORD=${GRAMPSWEB_ADMIN_PASSWORD}
|
||||||
- GRAMPSWEB_TREE=${GRAMPSWEB_TREE:-Stiftung}
|
- GRAMPSWEB_TREE=${GRAMPSWEB_TREE:-Stiftung}
|
||||||
- GRAMPSWEB_BASE_URL=/ahnenforschung
|
- GRAMPSWEB_BASE_URL=${GRAMPSWEB_BASE_URL:-/ahnenforschung}
|
||||||
|
- GRAMPSWEB_STATIC_PATH=${GRAMPSWEB_STATIC_PATH:-/ahnenforschung/static}
|
||||||
|
- GRAMPSWEB_STATIC_URL=${GRAMPSWEB_STATIC_URL:-/ahnenforschung/static/}
|
||||||
- GRAMPSWEB_CELERY_CONFIG__broker_url=redis://redis:6379/0
|
- GRAMPSWEB_CELERY_CONFIG__broker_url=redis://redis:6379/0
|
||||||
- GRAMPSWEB_CELERY_CONFIG__result_backend=redis://redis:6379/0
|
- GRAMPSWEB_CELERY_CONFIG__result_backend=redis://redis:6379/0
|
||||||
- GRAMPSWEB_RATELIMIT_STORAGE_URI=redis://redis:6379/1
|
- GRAMPSWEB_RATELIMIT_STORAGE_URI=redis://redis:6379/1
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
# =============================================================================
|
# =============================================================================
|
||||||
# PRODUCTION ENVIRONMENT VARIABLES
|
# PRODUCTION ENVIRONMENT VARIABLES TEMPLATE
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# This template shows the required environment variables for production.
|
# ⚠️ THIS IS A TEMPLATE ONLY - DO NOT PUT REAL SECRETS HERE!
|
||||||
#
|
#
|
||||||
# SETUP INSTRUCTIONS:
|
# SETUP INSTRUCTIONS:
|
||||||
# 1. SSH into production server: ssh user@your-server-ip
|
# 1. SSH into production server: ssh user@your-server-ip
|
||||||
# 2. Navigate to stiftung directory: cd /opt/stiftung
|
# 2. Navigate to stiftung directory: cd /opt/stiftung
|
||||||
# 3. Copy this template: cp env-production.template .env
|
# 3. Copy this template: cp env-production.template .env
|
||||||
# 4. Edit with real values: nano .env
|
# 4. Edit with REAL values: nano .env
|
||||||
# 5. Set secure permissions: chmod 600 .env
|
# 5. Set secure permissions: chmod 600 .env
|
||||||
#
|
#
|
||||||
# IMPORTANT: Once created, this file will NEVER be overwritten by git deployments!
|
# 🔒 SECURITY:
|
||||||
# The .env file is in .gitignore and will be preserved across all future deployments.
|
# - The real .env file stays ONLY on the production server
|
||||||
|
# - This template is safe to commit to Git (no real secrets)
|
||||||
|
# - Git deployments will NEVER overwrite your real .env file
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
# DATABASE CONFIGURATION
|
# DATABASE CONFIGURATION
|
||||||
@@ -51,6 +53,12 @@ GRAMPSWEB_SECRET_KEY=your_grampsweb_secret_key_here
|
|||||||
GRAMPSWEB_ADMIN_EMAIL=admin@vhtv-stiftung.de
|
GRAMPSWEB_ADMIN_EMAIL=admin@vhtv-stiftung.de
|
||||||
GRAMPSWEB_ADMIN_PASSWORD=your_grampsweb_admin_password_here
|
GRAMPSWEB_ADMIN_PASSWORD=your_grampsweb_admin_password_here
|
||||||
|
|
||||||
|
# GRAMPS API CONNECTION (for Django integration)
|
||||||
|
GRAMPS_URL=http://grampsweb:5000
|
||||||
|
GRAMPS_USERNAME=admin@vhtv-stiftung.de
|
||||||
|
GRAMPS_PASSWORD=your_grampsweb_admin_password_here
|
||||||
|
GRAMPS_API_TOKEN=your_gramps_api_token_if_needed
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# GENERATE SECRET KEYS:
|
# GENERATE SECRET KEYS:
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|||||||