From df0d419c46e3ba2c02e2c028e0461ff402d6a5a6 Mon Sep 17 00:00:00 2001 From: Leopoldadmin Date: Mon, 15 Jun 2026 22:02:09 +0000 Subject: [PATCH] Update app.py with full CRM code --- app.py | 257 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 256 insertions(+), 1 deletion(-) diff --git a/app.py b/app.py index 6ea711c..5a4972d 100644 --- a/app.py +++ b/app.py @@ -1 +1,256 @@ -§§include(/a0/usr/workdir/dev-projects/leocrm/app.py) \ No newline at end of file +"""LeoCRM - Minimal CRM with auth, companies, contacts.""" +import os +import sqlite3 +from datetime import datetime +from functools import wraps + +from flask import Flask, render_template, request, redirect, url_for, flash, session, g +from werkzeug.security import generate_password_hash, check_password_hash + +app = Flask(__name__) +app.secret_key = os.urandom(24).hex() +DATABASE = os.path.join(os.path.dirname(__file__), 'leocrm.db') + + +def get_db(): + if 'db' not in g: + g.db = sqlite3.connect(DATABASE) + g.db.row_factory = sqlite3.Row + g.db.execute("PRAGMA foreign_keys = ON") + return g.db + + +@app.teardown_appcontext +def close_db(exception): + db = g.pop('db', None) + if db is not None: + db.close() + + +def init_db(): + db = sqlite3.connect(DATABASE) + db.executescript(''' + CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT UNIQUE NOT NULL, + password_hash TEXT NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ); + CREATE TABLE IF NOT EXISTS companies ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + address TEXT, + phone TEXT, + email TEXT, + website TEXT, + notes TEXT, + user_id INTEGER NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users(id) + ); + CREATE TABLE IF NOT EXISTS contacts ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + first_name TEXT NOT NULL, + last_name TEXT NOT NULL, + email TEXT, + phone TEXT, + position TEXT, + notes TEXT, + company_id INTEGER NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE CASCADE + ); + ''') + db.commit() + db.close() + + +def login_required(f): + @wraps(f) + def decorated(*args, **kwargs): + if 'user_id' not in session: + flash('Bitte melde dich an.', 'warning') + return redirect(url_for('login')) + return f(*args, **kwargs) + return decorated + + +@app.route('/') +def index(): + if 'user_id' in session: + return redirect(url_for('dashboard')) + return redirect(url_for('login')) + + +@app.route('/register', methods=['GET', 'POST']) +def register(): + if request.method == 'POST': + username = request.form['username'].strip() + password = request.form['password'] + if not username or not password: + flash('Benutzername und Passwort sind erforderlich.', 'danger') + return render_template('register.html') + db = get_db() + existing = db.execute('SELECT id FROM users WHERE username = ?', (username,)).fetchone() + if existing: + flash('Benutzername bereits vergeben.', 'danger') + return render_template('register.html') + db.execute('INSERT INTO users (username, password_hash) VALUES (?, ?)', + (username, generate_password_hash(password))) + db.commit() + flash('Registrierung erfolgreich! Bitte melde dich an.', 'success') + return redirect(url_for('login')) + return render_template('register.html') + + +@app.route('/login', methods=['GET', 'POST']) +def login(): + if request.method == 'POST': + username = request.form['username'].strip() + password = request.form['password'] + db = get_db() + user = db.execute('SELECT * FROM users WHERE username = ?', (username,)).fetchone() + if user and check_password_hash(user['password_hash'], password): + session['user_id'] = user['id'] + session['username'] = user['username'] + flash(f'Willkommen, {username}!', 'success') + return redirect(url_for('dashboard')) + flash('Ungültige Anmeldedaten.', 'danger') + return render_template('login.html') + + +@app.route('/logout') +def logout(): + session.clear() + flash('Du wurdest abgemeldet.', 'info') + return redirect(url_for('login')) + + +@app.route('/dashboard') +@login_required +def dashboard(): + db = get_db() + companies = db.execute( + 'SELECT * FROM companies WHERE user_id = ? ORDER BY name', + (session['user_id'],) + ).fetchall() + return render_template('dashboard.html', companies=companies) + + +@app.route('/companies/create', methods=['GET', 'POST']) +@login_required +def company_create(): + if request.method == 'POST': + db = get_db() + db.execute('INSERT INTO companies (name, address, phone, email, website, notes, user_id) VALUES (?,?,?,?,?,?,?)', + (request.form['name'], request.form.get('address',''), request.form.get('phone',''), + request.form.get('email',''), request.form.get('website',''), request.form.get('notes',''), + session['user_id'])) + db.commit() + flash('Firma erstellt.', 'success') + return redirect(url_for('dashboard')) + return render_template('company_form.html', company=None) + + +@app.route('/companies//edit', methods=['GET', 'POST']) +@login_required +def company_edit(id): + db = get_db() + company = db.execute('SELECT * FROM companies WHERE id = ? AND user_id = ?', + (id, session['user_id'])).fetchone() + if not company: + flash('Firma nicht gefunden.', 'danger') + return redirect(url_for('dashboard')) + if request.method == 'POST': + db.execute('UPDATE companies SET name=?, address=?, phone=?, email=?, website=?, notes=? WHERE id=?', + (request.form['name'], request.form.get('address',''), request.form.get('phone',''), + request.form.get('email',''), request.form.get('website',''), request.form.get('notes',''), id)) + db.commit() + flash('Firma aktualisiert.', 'success') + return redirect(url_for('dashboard')) + return render_template('company_form.html', company=company) + + +@app.route('/companies//delete', methods=['POST']) +@login_required +def company_delete(id): + db = get_db() + db.execute('DELETE FROM companies WHERE id = ? AND user_id = ?', (id, session['user_id'])) + db.commit() + flash('Firma gelöscht.', 'info') + return redirect(url_for('dashboard')) + + +@app.route('/companies//contacts') +@login_required +def contact_list(company_id): + db = get_db() + company = db.execute('SELECT * FROM companies WHERE id = ? AND user_id = ?', + (company_id, session['user_id'])).fetchone() + if not company: + flash('Firma nicht gefunden.', 'danger') + return redirect(url_for('dashboard')) + contacts = db.execute('SELECT * FROM contacts WHERE company_id = ? ORDER BY last_name, first_name', + (company_id,)).fetchall() + return render_template('contact_list.html', company=company, contacts=contacts) + + +@app.route('/companies//contacts/create', methods=['GET', 'POST']) +@login_required +def contact_create(company_id): + db = get_db() + company = db.execute('SELECT * FROM companies WHERE id = ? AND user_id = ?', + (company_id, session['user_id'])).fetchone() + if not company: + flash('Firma nicht gefunden.', 'danger') + return redirect(url_for('dashboard')) + if request.method == 'POST': + db.execute('INSERT INTO contacts (first_name, last_name, email, phone, position, notes, company_id) VALUES (?,?,?,?,?,?,?)', + (request.form['first_name'], request.form['last_name'], request.form.get('email',''), + request.form.get('phone',''), request.form.get('position',''), request.form.get('notes',''), company_id)) + db.commit() + flash('Kontaktperson erstellt.', 'success') + return redirect(url_for('contact_list', company_id=company_id)) + return render_template('contact_form.html', company=company, contact=None) + + +@app.route('/contacts//edit', methods=['GET', 'POST']) +@login_required +def contact_edit(id): + db = get_db() + contact = db.execute('''SELECT c.*, co.name as company_name, co.user_id + FROM contacts c JOIN companies co ON c.company_id = co.id + WHERE c.id = ? AND co.user_id = ?''', + (id, session['user_id'])).fetchone() + if not contact: + flash('Kontakt nicht gefunden.', 'danger') + return redirect(url_for('dashboard')) + if request.method == 'POST': + db.execute('UPDATE contacts SET first_name=?, last_name=?, email=?, phone=?, position=?, notes=? WHERE id=?', + (request.form['first_name'], request.form['last_name'], request.form.get('email',''), + request.form.get('phone',''), request.form.get('position',''), request.form.get('notes',''), id)) + db.commit() + flash('Kontakt aktualisiert.', 'success') + return redirect(url_for('contact_list', company_id=contact['company_id'])) + return render_template('contact_form.html', company={'id': contact['company_id'], 'name': contact['company_name']}, contact=contact) + + +@app.route('/contacts//delete', methods=['POST']) +@login_required +def contact_delete(id): + db = get_db() + contact = db.execute('''SELECT c.company_id, co.user_id + FROM contacts c JOIN companies co ON c.company_id = co.id + WHERE c.id = ?''', (id,)).fetchone() + if contact and contact['user_id'] == session['user_id']: + db.execute('DELETE FROM contacts WHERE id = ?', (id,)) + db.commit() + flash('Kontakt gelöscht.', 'info') + return redirect(url_for('contact_list', company_id=contact['company_id'])) + flash('Kontakt nicht gefunden.', 'danger') + return redirect(url_for('dashboard')) + + +if __name__ == '__main__': + init_db() + app.run(host='0.0.0.0', port=5000, debug=True)