Merge branch 'development' of gitea.centx.de:lelo/cdh-merger into development

This commit is contained in:
lelo 2025-06-18 13:02:38 +02:00
commit f3aa4d781b
3 changed files with 247 additions and 89 deletions

View File

@ -76,10 +76,14 @@ def get_merged_df(table_name): # return table_name: str
stripe_adjustment['norm_date'] = pd.to_datetime(stripe_adjustment['Created'], format='%Y-%m-%d %H:%M')
stripe_adjustment['norm_amount'] = stripe_adjustment['Amount'].astype(str).str.replace(',', '.').astype(float)
stripe_adjustment['norm_zweck'] = "Korrekturen"
stripe_adjustment['norm_name'] = "Verrechnung Korrekturen"
stripe_adjustment['norm_currency'] = stripe_adjustment['Currency'].astype(str).str.upper()
stripe_stripeFee['norm_date'] = pd.to_datetime(stripe_stripeFee['Created'], format='%Y-%m-%d %H:%M')
stripe_stripeFee['norm_amount'] = stripe_stripeFee['Amount'].astype(str).str.replace(',', '.').astype(float)
stripe_stripeFee['norm_zweck'] = "Stripe"
stripe_stripeFee['norm_name'] = "Verrechnung Stripe"
stripe_stripeFee['norm_currency'] = stripe_stripeFee['Currency'].astype(str).str.upper()
# Extract the “py_…” token from stripe_refund description
stripe_refund['norm_payment_id'] = stripe_refund['Description'].str.extract(r'(py_[A-Za-z0-9]+)')
@ -92,6 +96,7 @@ def get_merged_df(table_name): # return table_name: str
stripe_charge['norm_date'] = pd.to_datetime(stripe_charge['Created'], format='%Y-%m-%d %H:%M')
stripe_charge['norm_amount'] = stripe_charge['Amount'].astype(str).str.replace(',', '.').astype(float)
stripe_charge['norm_email'] = stripe_charge['Customer Email'].fillna('').astype(str)
stripe_charge['norm_currency'] = stripe_charge['Currency'].astype(str).str.upper()
stripe_charge['norm_name'] = stripe_charge.apply(
lambda r: r['Customer Name'] or r['Details'], axis=1
)
@ -110,6 +115,7 @@ def get_merged_df(table_name): # return table_name: str
raisenow['norm_amount'] = raisenow['Betrag'].astype(float)
raisenow['norm_email'] = raisenow['E-Mail-Adresse'].astype(str)
raisenow['norm_name'] = raisenow['Vorname'].astype(str) + ' ' + raisenow['Nachname'].astype(str)
raisenow['norm_currency'] = raisenow['Währung'].astype(str).str.upper()
# start with twostep assignment
raisenow['norm_zweck'] = raisenow.apply(
@ -244,7 +250,7 @@ def get_merged_df(table_name): # return table_name: str
srow = stripe_charge.loc[s_idx].to_dict()
rrow = raisenow.loc[r_idx].to_dict()
# drop any overlapping keys so we never get suffixes
for k in ['norm_amount','norm_name','norm_date','norm_email','idx_stripe']:
for k in ['norm_name','norm_date','norm_email','norm_amount','norm_currency','idx_stripe']:
rrow.pop(k, None)
# now combine so stripe values win for those keys, and raisenow adds its own columns
merged = {**srow, **rrow}
@ -252,7 +258,7 @@ def get_merged_df(table_name): # return table_name: str
combined = pd.DataFrame(merged_rows)
starting_columns = ['norm_name', 'norm_date', 'norm_email', 'norm_amount', 'norm_zweck']
starting_columns = ['norm_name', 'norm_date', 'norm_email', 'norm_amount', 'norm_currency', 'norm_zweck']
# reorder columns to put the most important ones first
combined = pd.concat([
combined[starting_columns],
@ -274,11 +280,15 @@ def get_merged_df(table_name): # return table_name: str
stripe_only = stripe_charge[~stripe_charge['idx_stripe'].isin(used)]
result = pd.concat([combined, stripe_only, stripe_adjustment, stripe_stripeFee], ignore_index=True)
# add the Stripe fees to the end of the table
# Set the timestamp to the last day of the month used by the dataset
latest_date = pd.to_datetime(result['norm_date']).max()
total_timestamp = pd.Timestamp(year=latest_date.year, month=latest_date.month, day=1) + pd.offsets.MonthEnd(0)
total_timestamp = total_timestamp.replace(hour=23, minute=59, second=59, microsecond=0)
new_rows = [
{'norm_zweck': 'Buchungsgebühren', 'norm_amount': total_stripe_charge_fees * (-1)},
{'norm_zweck': 'Rückbuchungsgebühren', 'norm_amount': total_stripe_refund_fees * (-1)},
{'norm_zweck': 'Korrekturgebühren', 'norm_amount': total_stripe_adjustment_fees * (-1)},
{'norm_zweck': 'Stripe Gebühren', 'norm_amount': total_stripe_stripeFee_fees * (-1)}
{'norm_name': 'Verrechnung Gebühren', 'norm_currency': 'EUR', 'norm_date': total_timestamp, 'norm_zweck': 'Buchungsgebühren', 'norm_amount': total_stripe_charge_fees * (-1)},
{'norm_name': 'Verrechnung Gebühren', 'norm_currency': 'EUR', 'norm_date': total_timestamp, 'norm_zweck': 'Rückbuchungsgebühren', 'norm_amount': total_stripe_refund_fees * (-1)},
{'norm_name': 'Verrechnung Gebühren', 'norm_currency': 'EUR', 'norm_date': total_timestamp, 'norm_zweck': 'Korrekturgebühren', 'norm_amount': total_stripe_adjustment_fees * (-1)},
{'norm_name': 'Verrechnung Gebühren', 'norm_currency': 'EUR', 'norm_date': total_timestamp, 'norm_zweck': 'Stripe Gebühren', 'norm_amount': total_stripe_stripeFee_fees * (-1)}
]
new_rows_df = pd.DataFrame(new_rows)
result = pd.concat([result, new_rows_df], ignore_index=True)
@ -293,6 +303,24 @@ def get_merged_df(table_name): # return table_name: str
if (pd.isna(row.get('norm_email')) or row.get('norm_email') == '') and pd.notna(row.get('E-Mail-Adresse')):
result.at[i, 'norm_email'] = f"{row.get('E-Mail-Adresse')}".strip()
# rename columns
result = result.rename(columns={
'norm_name': 'name',
'norm_date': 'booking_date',
'norm_email': 'email',
'norm_amount': 'amount',
'norm_currency': 'currency',
'norm_zweck': 'reference'
})
# add sign column based on amount
result['sign'] = result['amount'].apply(lambda x: 'CRDT' if x >= 0 else 'DBIT')
# sort columns
result = result[[
'booking_date', 'name', 'email', 'amount', 'currency', 'sign', 'reference'
]]
else:
raise ValueError(f"Unknown table_name '{table_name}'")
@ -351,8 +379,8 @@ def get_table():
})
@app.route('/download')
def download():
@app.route('/download_xlsx')
def download_xlsx():
sheets = {
name: get_merged_df(name)
for name in [
@ -392,6 +420,33 @@ def download():
mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
)
@app.route('/download_mt940')
def download_mt940():
df = get_merged_df('export')
mt940_string = generate_mt940(
df,
account_iban = "11223344/55667788",
transaction_ref = "REFEXCELEXPORT",
statement_number= "00000",
opening_balance = 0.0,
txn_code = "NMSC",
txn_ref = "NONREF",
info_prefix = "169?00RAISENOW??20"
)
output = BytesIO()
output.write(mt940_string.encode('utf-8'))
output.seek(0)
return send_file(
output,
as_attachment=True,
download_name='export_mt940.txt',
mimetype='text/plain'
)
@app.route('/clear_session', methods=['POST'])
def clear_session():
"""
@ -400,98 +455,131 @@ def clear_session():
session.clear()
return jsonify({'status': 'session cleared'})
def export_to_special_format(
df: pd.DataFrame,
reference: str,
account: str,
statement_number: int,
opening_date: datetime,
opening_balance: float,
currency: str,
closing_date: datetime = None,
closing_balance: float = None
) -> str:
def wrap_string(text: str, max_length: int = 65) -> str:
"""
Convert a DataFrame of transactions into the special SWIFT-like file format.
Wraps `text` at exactly `max_length` characters, inserting "\r\n" every max_length chars.
Existing line breaks are preserved (each line is wrapped separately).
"""
wrapped_lines = []
# split on any existing newline (handles "\n", "\r\n", etc.)
for line in text.splitlines():
# chop each line into max_length pieces
for i in range(0, len(line), max_length):
wrapped_lines.append(line[i : i + max_length])
# re-join with Windows-style breaks
return "\r\n".join(wrapped_lines)
def generate_mt940(df: pd.DataFrame,
account_iban: str,
transaction_ref: str,
statement_number: str = None,
opening_balance: float = 0.0,
txn_code: str = 'NMSC',
txn_ref: str = 'NONREF',
info_prefix: str = None) -> str:
"""
Generate an MT940 text statement in the custom style shown above.
Parameters
----------
df : pd.DataFrame
Must contain columns:
- 'value_date' (datetime)
- 'booking_date' (datetime)
- 'dc' (str): 'C' for credit, 'D' for debit
- 'amount' (float)
- optional 'transaction_code' (str)
- optional 'bank_reference' (str)
- 'narrative' (str)
reference : str
Message reference for :20:
account : str
Account number for :25:
statement_number : int
Statement sequence for :28C: (will be zero-padded to 5 digits)
opening_date : datetime
Opening balance date
opening_balance : float
Opening balance amount (positive)
currency : str
Three-letter currency code (e.g. 'EUR')
closing_date : datetime, optional
Closing balance date
closing_balance : float, optional
Closing balance amount (positive)
Columns required:
- 'booking_date' (datetime or str YYYY-MM-DD)
- 'amount' (float)
- 'currency' (str, e.g. 'EUR')
- 'sign' (str, 'CRDT' or 'DBIT')
- 'reference' (str, used inside your info_prefix section)
- 'name' (str, appended after ?32 in tag 86)
account_iban : str
Goes into tag 25 exactly as you want it (e.g. "11223344/55667788").
transaction_ref : str
Tag 20 (e.g. "REFEXCELEXPORT")
statement_number : str, optional
If given, used verbatim for tag 28C (e.g. "00000"); otherwise falls back to
"{transaction_ref}/1"
opening_balance : float, optional
Starting balance for tag 60F
txn_code : str, optional
The 3-letter code in your :61: line (default "NMSC")
txn_ref : str, optional
The literal reference after that code (default "NONREF")
info_prefix : str, optional
If you set e.g. "169?00RAISENOW??20", your tag 86 lines become
169?00RAISENOW??20<reference> ?32<name>
If you leave it `None`, we fall back to a simple `<name> <reference>` join.
Returns
-------
str
The formatted file content.
A single string with CRLF line endings.
"""
# normalize & sort
df2 = df.copy()
df2['booking_date'] = pd.to_datetime(df2['booking_date'])
df2.sort_values('booking_date', inplace=True)
# constant currency
currency = df2['currency'].iat[0]
lines = []
# Header
lines.append(f":20:{reference}")
lines.append(f":25:{account}")
lines.append(f":28C:{statement_number:05d}")
# header
lines.append(f":20:{transaction_ref}")
lines.append(f":25:{account_iban}")
if statement_number is None:
lines.append(f":28C:{transaction_ref}/1")
else:
lines.append(f":28C:{statement_number}")
# Opening balance :60F:
od = opening_date.strftime('%y%m%d')
ob = f"{opening_balance:,.2f}".replace(',', 'X').replace('.', ',').replace('X', '')
lines.append(f":60F:C{od}{currency}{ob}")
# opening balance
first_dt = df2['booking_date'].iat[0]
ob_sign = 'C' if opening_balance >= 0 else 'D'
ob_amt = abs(opening_balance)
ob_str = f"{ob_amt:.2f}".replace('.', ',')
lines.append(f":60F:{ob_sign}{first_dt.strftime('%y%m%d')}{currency}{ob_str}")
# Transactions
for _, row in df.iterrows():
vd = row['value_date'].strftime('%y%m%d')
bd = row['booking_date'].strftime('%m%d')
dc = row['dc']
amt = f"{row['amount']:,.2f}".replace(',', 'X').replace('.', ',').replace('X', '')
tcode = row.get('transaction_code', '')
bref = row.get('bank_reference', '')
lines.append(f":61:{vd}{bd}{dc}{amt}{tcode}{bref}")
lines.append(f":86:{row['narrative']}")
# transactions
for _, row in df2.iterrows():
bd = row['booking_date']
sign = 'C' if row['sign']=='CRDT' else 'D'
amt = abs(row['amount'])
amt_str = f"{amt:.2f}".replace('.', ',')
# Closing balance :62F:
if closing_date and closing_balance is not None:
cd = closing_date.strftime('%y%m%d')
cb = f"{closing_balance:,.2f}".replace(',', 'X').replace('.', ',').replace('X', '')
lines.append(f":62F:C{cd}{currency}{cb}")
# :61:YYMMDDMMDD[C|D]amount<txn_code><txn_ref>
lines.append(
f":61:{bd.strftime('%y%m%d')}"
f"{bd.strftime('%m%d')}"
f"{sign}{amt_str}"
f"{txn_code}{txn_ref}"
)
return "\n".join(lines)
# :86: either structured or simple fallback
raw_rem = row.get('reference', '')
raw_name = row.get('name', '')
rem = '' if pd.isna(raw_rem) else str(raw_rem)
name = '' if pd.isna(raw_name) else str(raw_name)
# Example usage:
# df = pd.DataFrame([...])
# content = export_to_special_format(
# df,
# reference='REFEXCELEXPORT',
# account='11223344/55667788',
# statement_number=0,
# opening_date=datetime(2025,3,6),
# opening_balance=0.00,
# currency='EUR',
# closing_date=datetime(2025,3,6),
# closing_balance=12048.71
# )
# with open('statement.txt', 'w') as f:
# f.write(content)
if info_prefix:
# your “169?00RAISENOW??20<reference> ?32<name>”
lines.append(f":86:{info_prefix}{rem} ?32{name}")
else:
# old-style "<name> <reference>"
info = " ".join(filter(None, [name, rem]))
lines.append(f":86:{info}")
# closing balance
net_mv = sum(
row['amount'] if row['sign']=='CRDT' else -row['amount']
for _, row in df2.iterrows()
)
closing = opening_balance + net_mv
cb_sign = 'C' if closing >= 0 else 'D'
cb_amt = abs(closing)
cb_str = f"{cb_amt:.2f}".replace('.', ',')
last_dt = df2['booking_date'].iat[-1]
lines.append(f":62F:{cb_sign}{last_dt.strftime('%y%m%d')}{currency}{cb_str}")
file_str = "\r\n".join(lines)
return wrap_string(file_str)
if __name__ == '__main__':

46
app/projects.json Normal file
View File

@ -0,0 +1,46 @@
{
"Allgemein": {"project_ID": "000"},
"Hilfe für Waisen und Witwen": {"project_ID": "001", "description": "HILFE FÜR WAISEN UND WITWEN - Hilfsaktion für bedürftige Waisen und Witwen. Projektleiter: Wall Nikolaus, 1. Vorsitzender Mobil. 01794740945, CDH-Stephanus e. V., speyer@cdh-stephanus.de, Verwendungszweck: „Hilfe für Waisen und Witwen“"},
"Hilfe für Behinderte": {"project_ID": "002", "description": "HILFE FÜR BEHINDERTE - Das Projekt unterstützt Kranke, Behinderte und in Not geratene Menschen. Projektleiter: Andreas und Larissa Stebner Mobil 0151/26602643, Verwendungszweck: „Hilfe für Behinderte“, Infoquelle: Wird meist unproblematisch gleich auf Anfrage zugeschickt oder telefonisch durchgegeben. Projektleitung: Stebner Andrej und Larissa"},
"Evangelisation": {"project_ID": "006", "description": "Evangelisation (weltweiter Projekt), Projektleiter: Wall Nikolaus, 1. Vorsitzender Mobil. 01794740945, CDH-Stephanus e. V., speyer@cdh-stephanus.de, Verwendungszweck: Evangelisation"},
"Stephanus-Nachrichten": {"project_ID": "008", "description": "MISSIONS GEMEINDENACHRICHTEN - Seit der Gründung des Hilfswerks „Stephanus“ werden unsere Spender durch die Zeitschrift „Gemeinde- und Missionsnachrichten“ über die Missionsarbeit informiert. Diese Zeitschrift wird durch ehrenamtliche Mitarbeiter von freien Evangeliums-Christengemeinden herausgegeben, Projektleiter: Siegfried Wentland, Tel. +49 421 608274, Verw. Zweck: „Missions-Nachrichten“"},
"Hilfe für Äthiopien": {"project_ID": "013", "description": "HILFE FÜR ÄTHIOPIEN - Dieses Projekt soll dazu dienen, der äthiopischen Bevölkerung Zugang zum Trinkwasser, sowie zum Wasser des Lebens Jesus Christus ermöglichen. Projektleiter: Waldemar Schulz (Gem. Buchholz), Mobil 0178/7579350, waldemar-schulz@hotmail.de, Verwendungszweck: „Äthiopien“"},
"Hilfe für Verfolgte Christen": {"project_ID": "014", "description": "HILFE FÜR VERFOLGTE CHRISTEN - Dieses Projekt ist für die Unterstützung der verfolgten Christen, für finanzielle und materielle Hilfe, Schulungen von Pastoren und Ausstattung der Gemeinden gedacht. Projektleiter: Alexander Siebert, Mobil 0172/1474429, siebertalexander82@gmail.com, Verwendungszweck: „Verfolgte Christen“"},
"Hilfe für Hoffnung für Kinder": {"project_ID": "015", "description": "HILFE FÜR HOFFNUNG FÜR KINDER - Das Projekt „Hoffnung für Kinder Belzy“ wurde für Kinder in der Not in Moldau eröffnet weil viele Familien nicht in der Lage sind, ihren Kindern einen ordentlichen Lebensstandard zu bieten. Projektleiter: Johannes Wiens, Mobil 0176/47086666, jo.bet@web.de, Verwendungszweck: „Hoffnung für Kinder Belzy“, Unterstutzt durch die FECG Mettenheim e.V."},
"Hilfe für Mädchenheim Arudpani Sri Lanka": {"project_ID": "016", "description": "HILFE FÜR MÄDCHENHEIM ARUDPANI, SRI LANKA - Seit 2005 unterstützen wir das Mädchenheim „Arudpani“. Im Moment befinden sich ca. 25 Mädchen im Heim wo sie christlich erzogen werden und eine Schulbildung bekommen. Projektleiter: Wall Reinhold, Mobil 0176/29262775, Verwendungszweck: „SL-Arudpani“"},
"Hilfe für Kinderheim in Rumänien": {"description": "Mission „Stephanus“ Arbeit in Rumänien durch Hilfsgütern und Finanzen für das Kinderheim „Debora“ in der Stadt Arad, die von den Gemeinden in Molbergen und Pforzheim unterstütz werden. Projektleiter: Ovidio Tiran Mobil 0151/27631582 htt-info@web.de, Verwendungszweck: „Rumänien Hilfe“"},
"Hilfe für Uganda": {"project_ID": "018", "description": "HILFE FÜR UGANDA - Im Oktober 2010 wurde durch A. Konradi eine Partnerorganisation (Tochtergesellschaft) von CDH-Stephanus e. V. „Stephanus Uganda“ im Dorf Seeta-Lukinga (Kyewanise) ins Leben gerufen. Dafür wurde ein Grundstück (12,5 Acre) für die Missionsstation gekauft. Das Hauptziel des Projektes ist es, die Lebensbedingungen der Bevölkerungsgruppe der Region (Mpigi District) im Sinne von Armutsbewältigung; sowie „geistlicher“ und körperlicher Gesundheit nachhaltig zu verbessern. Im März 2011 wurde dort ein Wasserbrunnen zur Versorgung von sauberem Wasser gebohrt. Im Jahr 2013 wurde ein Kinderheim errichtet, das zurzeit 35 waise bzw. benachteiligte Kinder beherbergt. Darüber hinaus wurde dort eine Schule errichtet. Durch unser Angebot von Erziehung und Bildung ermöglichen wir es den jungen Menschen, beruflichen Beschränkungen auszuweichen. Projektleiter: Albert Hiller Mobil. 0163/6114900, Jack David Kayindu Mobil 0157/30656004, Verwendungszweck: „Uganda“"},
"Hilfe für Reha Zentrum Chasara Lechaim in Israel": {"project_ID": "019", "description": "HILFE REHA-ZENTRUM CHASARA LECHAIM IN ISRAEL - Die Mission Stephanus unterstützt in Israel ein Rehabilitationszentrum für Alkohol- und Drogenabhängige. Im Rehabilitationszentrum leben durchschnittlich 10 Personen. Projektleiter: Erich Dojan, Mobil 0172/1390640, erichdojan@gmx.de, Verwendungszweck: „Chasara-Lechaim“, Infoquelle: Infos werden direkt von Eduard Betiev aus Israel geschickt."},
"Hilfe für Kinder Pateschaften in Uganda": {"project_ID": "020", "description": "KIINDER PATENSCHAFTEN IN UGANDA - Patenschaften in Form von Heimpatenschaften und Schulpatenschaften möglich! Projektleiter: Alexander Penkowski Mobil. 0177/4756150, Jack David Kayindu Mobil 0157/30656004, Verwendungszweck: „Kinderpatenschaft Uganda“"},
"Hilfe für Gemeinde in Israel": {"project_ID": "021", "description": "HILFE FÜR GEMEINDE IN ISRAEL - Die Mission Stephanus unterstützt in Israel eine Gemeinde und dadurch die Evangelisation und ein Rehabilitationszentrum für Alkohol- und Drogenabhängige. Im Rehabilitationszentrum leben durchschnittlich 5 Personen. Infoquelle: Infos werden direkt aus Israel von Valentin Negura zugeschickt. Projektleiter: Viktor Folz, Mobil 0175/2400696, viktor.folz58@gmail.com, Verwendungszweck: „Israel“, Verantwortliche in Israel: Kisselyov Valery, Leiter der Mission „Teiwat apachamim“, Maalot, Str. Snir 5 / 3 Box 7314, Israel, E-Mail maalot98@yandex.ru und Valentin Negura, der Gemeindeverantwortliche in Maalot"},
"Missionar Kellinger": {"project_ID": "022", "description": "Im Januar 2022 reiste das junge Ehepaar Samuel und Eva Kellinger mit ihrem kleinen Sohn nach Uganda. Vor Ort betreuten sie das Stephanus-Projekt. Er leistet zusammen mit einem Pastor Gemeinde und Jugendarbeit. Projektleiter: Matthias Krüger, Verwendungszweck: „Missionar in Afrika“"},
"Liebe drängt uns... (Buch": {"project_ID": "023"},
"Konferen": {"project_ID": "024"},
"Hilfe für Togo": {"project_ID": "025", "description": "PROJEKT TOGO Hilfe für WESTAFRIKA - Togo (Westafrika) Hilfe zur Selbsthilfe (Getreideanbau, Viehzucht), Die Gemeinde Ulmen unterstützt das Projekt in Togo in Zusammenarbeit mit dem einheimischen Pastor Williams. Ziel dieses Projekts sind der Gemeindeaufbau und die Evangelisation. Außerdem werden Waisenkinder oder Halbwaisen unterstützt. Projektleiter: Paul Altmann, Tel. 0176 46046914, paulaltmann65@gmail.com, Verwendungszweck: „TOGO“"},
"Missionar Hense": {"project_ID": "026"},
"Hilfe für Kurzfristige Projekte - div. Gemeinden": {"project_ID": "034", "description": "Kurzfristige Projekte - Hilfsaktion für bedürftige, kranke oder in Not geratene Menschen, Projektleiter: Wall Nikolaus, 1. Vorsitzender Mobil. 01794740945, CDH-Stephanus e. V., speyer@cdh-stephanus.de, Verwendungszweck: Aktuelle Not, z. B. Hausbrandt Fam. XY"},
"Hilfe für Katastrophen und Kriege": {"project_ID": "035", "description": "HILFE FÜR KATASTROPHEN & KRIEGE - Eine Katastrophe ist immer ein unerwartetes Ereignis, bei dem zahlreiche Menschen getötet oder verletzt werden, oder aber ihr Eigentum beschädigt oder zerstört wird. Es gibt Hilfseinsätze nach Naturkatastrophen, technischen Unfällen (Brand, Explosionen), terroristischen Anschlägen und kriegerischen Ereignissen. Es muss sofort gehandelt werden, daher ist eine Rücklage für dieses Projekt notwendig. Projektleiter: Mission Stephanus e. V., speyer@cdh-stephanus.de Tel. 06232-9191555, Verwendungszweck: „Katastrophen & Kriege“ mit einem aktuellen Hinweis z.B. Hochwasser"},
"Erdbeben Türkei/Syrien": {"project_ID": "036", "description": "ERDBEBEN IN DER TÜRKEI / SYRIEN - Eine Katastrophe ist immer ein unerwartetes Ereignis, bei dem zahlreiche Menschen getötet oder verletzt werden, oder aber ihr Eigentum beschädigt oder zerstört wird. Es muss sofort gehandelt werden, daher ist eine Rücklage für dieses Projekt notwendig. Projektleiter: Mission Stephanus e. V., speyer@cdh-stephanus.de Tel. 06232-9191555, Verwendungszweck: „Erdbeben Türkei“"},
"Hilfe für Weihnachtsaktion": {"project_ID": "044", "description": "HILFE FÜR WEIHNACHTSAKTION - Projektleiter: Mission Stephanus e. V., speyer@cdh-stephanus.de Tel. 06232-9191555, Verwendungszweck: „Weihnachtsaktion"},
"Hilfe für Freizeit an Gehörlose": {"project_ID": "045", "description": "Freizeit für Gehörlose, Projektleiter: Wall Nikolaus, 1. Vorsitzender Mobil. 01794740945, CDH-Stephanus e. V., speyer@cdh-stephanus.de, Verwendungszweck: Verwendungszweck: Freizeit Gehörlose"},
"Hilfe für Kirgisien": {"project_ID": "050", "description": "Hilfe für Kirgisien, Projektleiter: Wall Nikolaus, 1. Vorsitzender Mobil. 01794740945, CDH-Stephanus e. V., speyer@cdh-stephanus.de, Verwendungszweck: Verwendungszweck: Kirgisien"},
"Hilfe für Rybnitza": {"project_ID": "050", "description": "Hilfe für Rybniza/Projektleiter vor Ort Panchina, Projektleiter: Wall Nikolaus, 1. Vorsitzender Mobil. 01794740945, CDH-Stephanus e. V., speyer@cdh-stephanus.de, Verwendungszweck: Verwendungszweck: Panchina"},
"Hilfe für Chisinau / Altenheim": {"project_ID": "053", "description": "HILFE FÜR CHISINAU IN MOLDAU - Projektleiter: Wassiljew Jakob Mob. 0162/1077390, wassiljew@icloud.com, Verwendungszweck: „Altenheim Sarepta“"},
"Hilfe Save Haus Talita (Äthiopien)": {"description": "Projektstart gescheitert und wird gelöscht"},
"Hilfe für Nischnij Novgorod (Russischeföderation)": {},
"Hilfe für Rehazentrum und neue Gemeinde in Nischni Novgorod (Baschmakov Andrej": {"project_ID": "050", "description": "Hilfe für Nischnij Novgorod (Russische Föderation), Projektleiter: Wall Nikolaus, 1. Vorsitzender Mobil. 01794740945, CDH-Stephanus e. V., speyer@cdh-stephanus.de, Verwendungszweck: Nischnij Novgorod"},
"Hilfe für Kurzfristige Kranke": {"project_ID": "069", "description": "Hilfe für Kranke (Sofothilfe für Kranke (Medikamente, Prothesen, OPs), Projektleiter: Wall Nikolaus, 1. Vorsitzender Mobil. 01794740945, CDH-Stephanus e. V., speyer@cdh-stephanus.de, Verwendungszweck: Sofothilfe für Kranke (Medikamente, Prothesen, OPs)"},
"Hilfe für Haus der Barmerzigkeut „Phildelphia“": {"project_ID": "071", "description": "Haus der Barmherzigkeit „PHiladelphia“ in Krivoj Rog, Ukraine, Projektleiter: Waldemar Just, Mobil. 0152 21554953 oder 06232/98668, CDH-Stephanus e. V., speyer@cdh-stephanus.de, Verwendungszweck: Philadelphia"},
"Hilfe für Fond Notleidende kinder": {"project_ID": "072", "description": "HILFE FÜR FOND NOTLEIDENDE KINDER - Fond Notleidenden Kinder ist seit 2000 tätig. Der Fond hat 16 Stammpunkte in Schulen, Gebetshäusern und christlichen Familien in denen insgesamt ca. 500 Kinder versorgt werden. Bei einem Stammpunkt bekommen die Kinder fünf Mal pro Woche geistige Nahrung und eine warme Mahlzeit (3 Gänge Menü). Projektleiter: Oleg Bogun, Tel. 0571/3988488, Mobil 0160/1232013, Spendenkonto: Stephanus e. V., Sparkasse Binden-Lübbecke, IBAN: DE56490501010040104671, BIC: WELADED1MI"},
"Hilfe für Kinder Patenschaften in Indien": {"project_ID": "075", "description": "KINDERPATENSCHAFTEN IN INDIEN - Seit der Gründung des CDH-Stephanus e. V. werden die Kinderpatenschaften in Indien in Zusammenarbeit mit der Inter-Mission im Hannover übernommen. Projektleiter: Witali Holstein, Tel. 04475/928366, witali.holstein@ewetel.net, Spendenkonto: Stephanus e. V., Old. Land. Bank, IBAN: DE25 2802 0050 3223 8396 00, BIC: OLBODEH2XXX"},
"Hilfe für Kinderheim in Philiphinen": {"project_ID": "076", "description": "Hilfe für Kinderheim in Philiphinen, Projektleiter: Markus Rutz, Tel. 01743214617, Verwendungszweck: „Philippinen Kinderheim“, Infos auf Anfrage"},
"Schule Manipur": {"project_ID": "077", "description": "Christliche Schule in Manipur Indien für Volksstämme der Tankul Bevölkerung. Projektleiter: Leo Altmann Ulmen"},
"Hilfe für Strahl der Hoffnung in Lrttland & UK": {"project_ID": "080", "description": "STRAHL DER HOFFNUNG IN LETTLAND & UKRAINE - Seit 2014 wird in Liepāja, Lettland in einem Haus Arbeit unter Straßenkindern geführt. Seit 2015 unterstützt „Strahl der Hoffnung“ die Arbeit in der Gebiet Cherson, Ukraine. In 5 Dörfern einmal in der Woche werden insgesamt bis zu 80 Kinder mit den warmen Essen versorgt. Projektleiter: Viktor Dalinger, Mobil 0178/4372310, v.f.dali@googlemail.com, Willi Krüger, Mobil 0176/84527187, willikrueger@gmx.de, Verwendungszweck: „Strahl der Hoffnung"},
"Hilfe für Bulgarien": {"project_ID": "085", "description": "HILFE FÜR BULGARIEN /Betreuung Gemeinde Speyer/Das Projekt „Jesus für Bulgarien“. Mit Hilfe der Gemeinde in Speyer werden seit 2012 Sachspenden und Lebensmittel sowie finanziell Hilfebedürftige unterstützt. Ziel ist der Aufbau von Gemeinden im Land und weiterhin diakonische Unterstützung von Bedürftigen. Projektleiter: Betz Reinhold, Mobil 0176/63399968, reinholdbetz@web.de, Gesswein Walter, Mobil 0176/70138468, w.gesswein@hotmail.de, Verwendungszweck:"},
"Brüderkasse": {"project_ID": "090", "description": "Projektleiter: Wall Nikolaus, 1. Vorsitzender Mobil. 01794740945, CDH-Stephanus e. V., speyer@cdh-stephanus.de"},
"Missionsreise": {"project_ID": "095", "description": "Alle Reisen die nicht mit einem bestimmten Projekt verbunden sind."},
"Reisen Projekt Verfolgte Christen": {"project_ID": "205", "description": "HILFE FÜR VERFOLGTE CHRISTEN - Dieses Projekt ist für die Unterstützung der verfolgten Christen, für finanzielle und materielle Hilfe, Schulungen von Pastoren und Ausstattung der Gemeinden gedacht. Projektleiter: Alexander Siebert, Mobil 0172/1474429, siebertalexander82@gmail.com, Verwendungszweck: „Verfolgte Christen“"},
"Reisen Äthiopie": {"project_ID": "213"},
"Reisen Sri Lanka": {"project_ID": "216", "description": "Missions-Reisegruppen nach Sri Lanka, Projektleiter: Irina Jähger Tel. 0172/1474429, Verwendungszweck: Namen_Vorname_Sri Lanka"},
"Reisen Uganda": {"project_ID": "218", "description": "Missions-Reisegruppen nach Uganda, Projektleiter: Irina Jähger Tel. 0172/1474429, Verwendungszweck: Namen_Vorname_Ugandareise"}
}

View File

@ -40,16 +40,17 @@
<button type="submit" class="btn btn-primary btn-sm">Upload</button>
</form>
<button id="download-excel" class="btn btn-success btn-sm me-3">Excel Download</button>
<button id="download-mt940" class="btn btn-info btn-sm me-3">MT940 Download</button>
<button id="clear-session" class="btn btn-warning btn-sm me-3">Daten löschen</button>
<div class="d-flex align-items-center">
<label for="table-select" class="form-label me-2 mb-0">Table:</label>
<select id="table-select" class="form-select form-select-sm">
<option value="export">Export</option>
<option value="stripe_import">Stripe Import</option>
<option value="raisenow_import">RaiseNow Import</option>
<option value="merged">Merged</option>
<option value="stripe_only">Stripe Only</option>
<option value="raisenow_only">RaiseNow Only</option>
<option value="export">Export</option>
</select>
</div>
</div>
@ -73,7 +74,9 @@
<script>
const uploadForm = document.getElementById('upload-form');
const tableSelect = document.getElementById('table-select');
const downloadBtn = document.getElementById('download-excel');
const download_xlsx_btn = document.getElementById('download-excel');
const download_camt_btn = document.getElementById('download-camt');
const download_mt940_btn = document.getElementById('download-mt940');
const clearBtn = document.getElementById('clear-session');
const loadingOverlay = document.getElementById('loadingOverlay');
let table;
@ -96,10 +99,10 @@
tableSelect.addEventListener('change', () => loadTable(tableSelect.value));
downloadBtn.addEventListener('click', async () => {
download_xlsx_btn.addEventListener('click', async () => {
showLoading();
try {
const resp = await fetch('/download');
const resp = await fetch('/download_xlsx');
if (!resp.ok) throw new Error('Download failed');
const blob = await resp.blob();
const url = URL.createObjectURL(blob);
@ -117,6 +120,27 @@
} finally { hideLoading(); }
});
download_mt940_btn.addEventListener('click', async () => {
showLoading();
try {
const resp = await fetch('/download_mt940');
if (!resp.ok) throw new Error('Download failed');
const blob = await resp.blob();
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
const disposition = resp.headers.get('Content-Disposition') || '';
const match = disposition.match(/filename="?([^";]+)"?/);
a.download = match ? match[1] : 'mt940.txt';
document.body.appendChild(a);
a.click();
a.remove();
URL.revokeObjectURL(url);
} catch (err) {
console.error(err); alert(err.message);
} finally { hideLoading(); }
});
clearBtn.addEventListener('click', async () => {
if (!confirm('Are you sure you want to clear the server session? This will reset all loaded data.')) return;
showLoading();