Fix and enhance CSV import templates
- Update Destinataer template: added 8 missing fields (ist_abkoemmling, haushaltsgroesse, monatliche_bezuege, vermoegen, unterstuetzung_bestaetigt, vierteljaehrlicher_betrag, studiennachweis_erforderlich, letzter_studiennachweis) - Update Laendereien template: added 20 missing fields including property details, tenant info, contract terms, financial data, and tax information - Fix JavaScript template download functionality: correct block name from extra_js to javascript - Add comprehensive debugging and error handling for download process - Improve CSV formatting with proper quoting for text fields containing spaces - Add fallback download methods for better browser compatibility All CSV templates now include complete field sets matching current model definitions.
This commit is contained in:
@@ -118,16 +118,16 @@
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="d-grid gap-2">
|
||||
<a href="#" class="btn btn-outline-success btn-sm" onclick="downloadTemplate('destinataere')">
|
||||
<a href="#" class="btn btn-outline-success btn-sm" onclick="downloadTemplate('destinataere'); return false;">
|
||||
<i class="fas fa-download"></i> Destinatäre-Vorlage
|
||||
</a>
|
||||
<a href="#" class="btn btn-outline-success btn-sm" onclick="downloadTemplate('paechter')">
|
||||
<a href="#" class="btn btn-outline-success btn-sm" onclick="downloadTemplate('paechter'); return false;">
|
||||
<i class="fas fa-download"></i> Pächter-Vorlage
|
||||
</a>
|
||||
<a href="#" class="btn btn-outline-success btn-sm" onclick="downloadTemplate('laendereien')">
|
||||
<a href="#" class="btn btn-outline-success btn-sm" onclick="downloadTemplate('laendereien'); return false;">
|
||||
<i class="fas fa-download"></i> Ländereien-Vorlage
|
||||
</a>
|
||||
<a href="#" class="btn btn-outline-secondary btn-sm" onclick="downloadTemplate('personen')">
|
||||
<a href="#" class="btn btn-outline-secondary btn-sm" onclick="downloadTemplate('personen'); return false;">
|
||||
<i class="fas fa-download"></i> Personen-Vorlage (Legacy)
|
||||
</a>
|
||||
</div>
|
||||
@@ -140,42 +140,87 @@
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
{% block javascript %}
|
||||
<script>
|
||||
function downloadTemplate(type) {
|
||||
console.log('downloadTemplate called with type:', type);
|
||||
let headers, filename, exampleRow;
|
||||
|
||||
if (type === 'destinataere') {
|
||||
headers = ['Vorname', 'Nachname', 'Familienzweig', 'E-Mail', 'Telefon', 'IBAN', 'Straße', 'PLZ', 'Ort', 'Geburtsdatum', 'Berufsgruppe', 'Ausbildungsstand', 'Institution', 'Projektbeschreibung', 'Jährliches_Einkommen', 'Finanzielle_Notlage', 'Notizen', 'Aktiv'];
|
||||
headers = ['Vorname', 'Nachname', 'Familienzweig', 'E-Mail', 'Telefon', 'IBAN', 'Straße', 'PLZ', 'Ort', 'Geburtsdatum', 'Berufsgruppe', 'Ausbildungsstand', 'Institution', 'Projektbeschreibung', 'Jährliches_Einkommen', 'Finanzielle_Notlage', 'Ist_Abkömmling', 'Haushaltsgroesse', 'Monatliche_Bezuege', 'Vermoegen', 'Unterstuetzung_Bestaetigt', 'Vierteljaehrlicher_Betrag', 'Studiennachweis_Erforderlich', 'Letzter_Studiennachweis', 'Notizen', 'Aktiv'];
|
||||
filename = 'destinataere_vorlage.csv';
|
||||
exampleRow = 'Max,Mustermann,hauptzweig,max@email.com,0123456789,DE12345678901234567890,Musterstraße 1,12345,Musterstadt,01.01.1990,student,Abitur,Universität Musterstadt,Studium der Informatik,15000,false,Beispiel Notiz,true';
|
||||
exampleRow = 'Max,Mustermann,hauptzweig,max@email.com,0123456789,DE12345678901234567890,Musterstraße 1,12345,Musterstadt,01.01.1990,student,Abitur,Universität Musterstadt,Studium der Informatik,15000,false,true,1,500,10000,false,400,false,,Beispiel Notiz,true';
|
||||
} else if (type === 'paechter') {
|
||||
headers = ['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'];
|
||||
filename = 'paechter_vorlage.csv';
|
||||
exampleRow = 'Hans,Bauer,hans@email.com,0123456789,DE12345678901234567890,Bauernhof 1,12345,Bauerndorf,natuerlich,01.01.1980,P001,01.01.2020,31.12.2029,5000,true,15,Ackerbau,Beispiel Notiz,true';
|
||||
} else if (type === 'laendereien') {
|
||||
headers = ['Lfd_Nr', 'EW_Nummer', 'Amtsgericht', 'Gemeinde', 'Gemarkung', 'Flur', 'Flurstück', 'Größe_qm', 'Grünland_qm', 'Acker_qm', 'Wald_qm', 'Sonstiges_qm', 'Verpachtete_Gesamtfläche_qm', 'Verp_Fläche_aktuell_qm', 'Aktiv', 'Notizen'];
|
||||
headers = ['Lfd_Nr', 'EW_Nummer', 'Grundbuchblatt', 'Amtsgericht', 'Gemeinde', 'Gemarkung', 'Flur', 'Flurstück', 'Adresse', 'Größe_qm', 'Grünland_qm', 'Acker_qm', 'Wald_qm', 'Sonstiges_qm', 'Verpachtete_Gesamtfläche_qm', 'Fläche_alte_Liste_qm', 'Verp_Fläche_aktuell_qm', 'Aktueller_Pächter', 'Pächter_Name', 'Pächter_Anschrift', 'Pachtbeginn', 'Pachtende', 'Verlängerung_Klausel', 'Zahlungsweise', 'Pachtzins_pro_ha', 'Pachtzins_pauschal', 'USt_Option', 'USt_Satz', 'Grundsteuer_Umlage', 'Versicherungen_Umlage', 'Verbandsbeiträge_Umlage', 'Jagdpacht_Anteil_Umlage', 'Anteil_Grundsteuer', 'Anteil_LWK', 'Aktiv', 'Notizen'];
|
||||
filename = 'laendereien_vorlage.csv';
|
||||
exampleRow = 'L001,EW001,Amtsgericht Musterstadt,Musterstadt,Mustergemarkung,1,123,10000,5000,3000,1500,500,8000,8000,true,Beispiel Notiz';
|
||||
exampleRow = 'L001,EW001,Grundbuch123,Amtsgericht Musterstadt,Musterstadt,Mustergemarkung,1,123,"Musterfeld 1",10000,5000,3000,1500,500,8000,7500,8000,,Max Musterpächter,"Max Musterpächter Bauernhof 1 12345 Dorf",2020-01-01,2029-12-31,true,jaehrlich,500.00,4000.00,false,19.00,true,true,true,false,100.00,50.00,true,"Beispiel Notiz"';
|
||||
} else if (type === 'personen') {
|
||||
headers = ['Vorname', 'Nachname', 'Familienzweig', 'E-Mail', 'Telefon', 'IBAN', 'Adresse', 'Geburtsdatum', 'Notizen', 'Aktiv'];
|
||||
filename = 'personen_legacy_vorlage.csv';
|
||||
exampleRow = 'Beispiel,Beispiel,hauptzweig,beispiel@email.com,0123456789,DE12345678901234567890,Beispielstraße 1,01.01.1990,Beispiel Notiz,true';
|
||||
}
|
||||
|
||||
console.log('Headers count:', headers ? headers.length : 'undefined');
|
||||
console.log('Filename:', filename);
|
||||
|
||||
// Create CSV content
|
||||
const csvContent = headers.join(',') + '\n' + exampleRow;
|
||||
console.log('CSV content length:', csvContent.length);
|
||||
|
||||
// Create download link
|
||||
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
|
||||
const link = document.createElement('a');
|
||||
const url = URL.createObjectURL(blob);
|
||||
link.setAttribute('href', url);
|
||||
link.setAttribute('download', filename);
|
||||
link.style.visibility = 'hidden';
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
try {
|
||||
// Create download link
|
||||
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
|
||||
|
||||
// Try the modern approach first
|
||||
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
|
||||
// For IE/Edge
|
||||
window.navigator.msSaveOrOpenBlob(blob, filename);
|
||||
console.log('Download via IE/Edge method');
|
||||
} else {
|
||||
// For other browsers
|
||||
const link = document.createElement('a');
|
||||
const url = URL.createObjectURL(blob);
|
||||
link.setAttribute('href', url);
|
||||
link.setAttribute('download', filename);
|
||||
link.style.visibility = 'hidden';
|
||||
link.style.display = 'none';
|
||||
document.body.appendChild(link);
|
||||
|
||||
// Force click
|
||||
setTimeout(() => {
|
||||
link.click();
|
||||
console.log('Link clicked');
|
||||
|
||||
// Clean up
|
||||
setTimeout(() => {
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(url);
|
||||
console.log('Cleanup completed');
|
||||
}, 100);
|
||||
}, 100);
|
||||
}
|
||||
console.log('Download should have started for:', filename);
|
||||
} catch (error) {
|
||||
console.error('Error in download:', error);
|
||||
|
||||
// Fallback: try data URL approach
|
||||
try {
|
||||
const dataUrl = 'data:text/csv;charset=utf-8,' + encodeURIComponent(csvContent);
|
||||
const link = document.createElement('a');
|
||||
link.setAttribute('href', dataUrl);
|
||||
link.setAttribute('download', filename);
|
||||
link.click();
|
||||
console.log('Fallback download method used');
|
||||
} catch (fallbackError) {
|
||||
console.error('Fallback download also failed:', fallbackError);
|
||||
alert('Fehler beim Download: ' + error.message + '\n\nBitte kopieren Sie den CSV-Inhalt aus der Browserkonsole.');
|
||||
console.log('CSV Content for manual copy:\n' + csvContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// File validation
|
||||
|
||||
140
deploy-production/docker-compose.prod.yml
Normal file
140
deploy-production/docker-compose.prod.yml
Normal file
@@ -0,0 +1,140 @@
|
||||
# Production Docker Compose Configuration
|
||||
# This file is used for production deployment via GitHub Actions
|
||||
# For local development, use: docker-compose -f compose.dev.yml up
|
||||
#
|
||||
# IMPORTANT: This configuration requires ALL environment variables to be
|
||||
# provided via the production server's .env file. No fallback values are
|
||||
# included for security reasons.
|
||||
|
||||
services:
|
||||
db:
|
||||
image: postgres:16-alpine
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: ${POSTGRES_DB}
|
||||
POSTGRES_USER: ${POSTGRES_USER}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
volumes:
|
||||
- dbdata:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
restart: unless-stopped
|
||||
|
||||
web:
|
||||
image: ghcr.io/remmerinio/stiftung-management-system:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_started
|
||||
environment:
|
||||
- POSTGRES_DB=${POSTGRES_DB}
|
||||
- POSTGRES_USER=${POSTGRES_USER}
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- DB_HOST=${DB_HOST}
|
||||
- DB_PORT=${DB_PORT}
|
||||
- DJANGO_SECRET_KEY=${DJANGO_SECRET_KEY}
|
||||
- DJANGO_DEBUG=${DJANGO_DEBUG}
|
||||
- DJANGO_ALLOWED_HOSTS=${DJANGO_ALLOWED_HOSTS}
|
||||
- LANGUAGE_CODE=${LANGUAGE_CODE}
|
||||
- TIME_ZONE=${TIME_ZONE}
|
||||
- REDIS_URL=${REDIS_URL}
|
||||
- PAPERLESS_API_URL=${PAPERLESS_API_URL}
|
||||
- PAPERLESS_API_TOKEN=${PAPERLESS_API_TOKEN}
|
||||
ports:
|
||||
- "8081:8000"
|
||||
volumes:
|
||||
- media_files:/app/media
|
||||
command: ["gunicorn", "core.wsgi:application", "--bind", "0.0.0.0:8000", "--workers", "3"]
|
||||
|
||||
worker:
|
||||
image: ghcr.io/remmerinio/stiftung-management-system:latest
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- POSTGRES_DB=${POSTGRES_DB}
|
||||
- POSTGRES_USER=${POSTGRES_USER}
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- DB_HOST=${DB_HOST}
|
||||
- DB_PORT=${DB_PORT}
|
||||
- DJANGO_SECRET_KEY=${DJANGO_SECRET_KEY}
|
||||
- DJANGO_DEBUG=${DJANGO_DEBUG}
|
||||
- REDIS_URL=${REDIS_URL}
|
||||
depends_on:
|
||||
- redis
|
||||
- db
|
||||
command: ["celery", "-A", "core", "worker", "-l", "info"]
|
||||
|
||||
beat:
|
||||
image: ghcr.io/remmerinio/stiftung-management-system:latest
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- POSTGRES_DB=${POSTGRES_DB}
|
||||
- POSTGRES_USER=${POSTGRES_USER}
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- DB_HOST=${DB_HOST}
|
||||
- DB_PORT=${DB_PORT}
|
||||
- DJANGO_SECRET_KEY=${DJANGO_SECRET_KEY}
|
||||
- DJANGO_DEBUG=${DJANGO_DEBUG}
|
||||
- REDIS_URL=${REDIS_URL}
|
||||
depends_on:
|
||||
- redis
|
||||
- db
|
||||
command: ["celery", "-A", "core", "beat", "-l", "info"]
|
||||
|
||||
grampsweb:
|
||||
image: ghcr.io/gramps-project/grampsweb:latest
|
||||
ports:
|
||||
- "8090:80"
|
||||
environment:
|
||||
- GRAMPSWEB_SECRET_KEY=${GRAMPSWEB_SECRET_KEY}
|
||||
- GRAMPSWEB_ADMIN_EMAIL=${GRAMPSWEB_ADMIN_EMAIL}
|
||||
- GRAMPSWEB_ADMIN_PASSWORD=${GRAMPSWEB_ADMIN_PASSWORD}
|
||||
volumes:
|
||||
- gramps_data:/app/data
|
||||
|
||||
paperless:
|
||||
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||
ports:
|
||||
- "8080:8000"
|
||||
environment:
|
||||
- PAPERLESS_REDIS=redis://redis:6379
|
||||
- PAPERLESS_DBHOST=db
|
||||
- PAPERLESS_DBPORT=5432
|
||||
- PAPERLESS_DBNAME=${POSTGRES_DB}
|
||||
- PAPERLESS_DBUSER=${POSTGRES_USER}
|
||||
- PAPERLESS_DBPASS=${POSTGRES_PASSWORD}
|
||||
- PAPERLESS_SECRET_KEY=${PAPERLESS_SECRET_KEY}
|
||||
- PAPERLESS_URL=https://vhtv-stiftung.de
|
||||
- PAPERLESS_ALLOWED_HOSTS=vhtv-stiftung.de,localhost
|
||||
- PAPERLESS_CORS_ALLOWED_HOSTS=https://vhtv-stiftung.de
|
||||
- PAPERLESS_FORCE_SCRIPT_NAME=/paperless
|
||||
- PAPERLESS_STATIC_URL=/paperless/static/
|
||||
- PAPERLESS_LOGIN_REDIRECT_URL=/paperless/
|
||||
- PAPERLESS_LOGOUT_REDIRECT_URL=/paperless/
|
||||
- PAPERLESS_ADMIN_USER=${PAPERLESS_ADMIN_USER}
|
||||
- PAPERLESS_ADMIN_PASSWORD=${PAPERLESS_ADMIN_PASSWORD}
|
||||
- PAPERLESS_ADMIN_MAIL=${PAPERLESS_ADMIN_MAIL}
|
||||
volumes:
|
||||
- paperless_data:/usr/src/paperless/data
|
||||
- paperless_media:/usr/src/paperless/media
|
||||
- paperless_export:/usr/src/paperless/export
|
||||
- paperless_consume:/usr/src/paperless/consume
|
||||
depends_on:
|
||||
- db
|
||||
- redis
|
||||
|
||||
volumes:
|
||||
dbdata:
|
||||
gramps_data:
|
||||
paperless_data:
|
||||
paperless_media:
|
||||
paperless_export:
|
||||
paperless_consume:
|
||||
media_files:
|
||||
Reference in New Issue
Block a user