# Van Emous CRM Eenvoudige CRM in Python (Flask) met SQLite, in de Van Emous-huisstijl. Versie 0.0.1. ## Functies - **Leads en klanten** (zoals in EspoCRM): status (nieuw → in behandeling → offerte → gewonnen/verloren), toewijzen aan een gebruiker, verwachte waarde, bron, omzetten van lead naar klant, tijdlijn met notities, e-mail, statuswissels en formulierinzendingen, bestanden en afbeeldingen, CSV-export. - **Relaties** (zoals accounts in EspoCRM), in twee soorten: **klanten** (bundels zoals een huishouden, familie of bedrijf, met meerdere contactpersonen en hun rol) en **partners** met een type (leverancier, aannemer, installateur, ...; de typen pas je aan bij Instellingen). Een lead omzetten naar klant zet de persoon in een nieuwe of bestaande klantrelatie. Leveranciers van producten worden automatisch partners. - **Taken/opvolging** per contact met datum en eigenaar; "Mijn taken" op het dashboard. - **API voor formulieren** (`POST /api/leads`): JSON, gewone formulieren en multipart met bestanden. Nederlandse en Engelse veldnamen worden herkend, onbekende velden bewaard. Dubbele leads (zelfde e-mail) komen bij het bestaande contact. Er is een honeypot (`_gotcha`) en een `redirect` naar een bedankpagina. Een `house-design`-object uit de configurator wordt als ontwerp bij de lead opgeslagen. Voorbeelden staan onder Instellingen. - **Import** van CSV en JSON voor leads/contactpersonen, relaties en producten, met een voorbeeld en kolomkoppeling. Het formaat van de configurator (`;`, komma-decimalen, BOM, `#`-regels) werkt direct. - **Inbox**: IMAP ophalen en SMTP versturen, mails automatisch gekoppeld aan contacten (op e-mailadres), contact aanmaken vanuit een mail, beantwoorden. - **Producten** met SKU als vaste sleutel, prijs, btw, eenheid, leverancier (partner) en afbeelding. Een import of `POST /api/products` werkt producten bij op SKU (alleen de meegegeven velden) en legt elke mutatie vast met de oude en de nieuwe waarde. Optioneel worden producten die niet meer in de lijst staan inactief gezet. Offerteregels bewaren hun eigen prijs, dus bestaande offertes veranderen niet. Een product dat in offertes gebruikt is, wordt bij verwijderen gearchiveerd. Export naar CSV in hetzelfde formaat als de import. - **Offertes** met regels (product of vrije regel), btw per tarief en een afdrukversie die je als PDF opslaat via de browser. - **Gebruikers** met de rollen beheerder (ook gebruikers en instellingen) en medewerker. - **Klantportaal** (`/portal`): de klant krijgt een uitnodigingslink (kopiëren of mailen vanaf het contact), stelt een wachtwoord in en kan dan offertes bekijken, accepteren of afwijzen, bestanden uploaden en berichten sturen. Een geaccepteerde offerte zet het contact op gewonnen/klant. - **Effecten** met GSAP (cdnjs, 3.12.5) volgens de motion-regels van de huisstijl, in `static/fx.js`. Ze staan uit bij `prefers-reduced-motion`, en na 3 seconden is de inhoud altijd zichtbaar. ## Starten ```sh python3 -m venv .venv .venv/bin/pip install -r requirements.txt .venv/bin/python app.py # http://127.0.0.1:5000 ``` Bij de eerste keer maak je het beheerdersaccount aan. Daarna vul je onder Instellingen de bedrijfsgegevens, de e-mail en de toegestane websites voor de API in. ## Online zetten Draai de app achter nginx/Apache met HTTPS, bijvoorbeeld met gunicorn: ```sh .venv/bin/pip install gunicorn .venv/bin/gunicorn -w 2 -b 127.0.0.1:8000 app:app ``` E-mail automatisch ophalen (cron, elke 10 minuten): ``` */10 * * * * cd /pad/naar/crm && .venv/bin/python app.py sync ``` ## Opslag Alles staat in `data/`: `crm.db` (SQLite), `uploads/` (bestanden), `secret.key` (sessies). Een back-up is een kopie van die map. Nieuwe kolommen worden bij het starten automatisch aan een bestaande database toegevoegd (`MIGRATIONS` in `app.py`). Houd `data/` buiten de webroot: er staan ook mailwachtwoorden in. `CRM_DATA=/ander/pad` verplaatst de datamap, `HOST` en `PORT` stellen de ontwikkelserver in. ## Structuur ``` app.py routes en logica importer.py CSV/JSON inlezen en kolommen herkennen mail.py IMAP/SMTP schema.sql database templates/ pagina's (Jinja) static/ style.css (huisstijltokens), fx.js (GSAP-effecten) en logo.svg ```