v0.0.1: eerste versie van de Van Emous CRM
Flask + SQLite, in de Van Emous-huisstijl (tokens uit het design system, GSAP-effecten volgens de motion-regels, uit bij prefers-reduced-motion). - Leads en contactpersonen: status, toewijzen, verwachte waarde, omzetten naar klant, tijdlijn, bestanden, taken/opvolging - Relaties (zoals accounts in EspoCRM): klantbundels (huishouden/familie) en partners met type (leverancier, aannemer, ...); leveranciers van producten worden automatisch partners - API voor formulieren (POST /api/leads) met dubbele-leaddetectie, bestanden en configurator-ontwerpen (house-design JSON) - Import van CSV/JSON (leads, relaties, producten) met kolomkoppeling; configurator-formaat - Producten met SKU als vaste sleutel, mutatiehistorie, POST /api/products, CSV-export; offerteregels houden hun eigen prijs - Offertes met btw per tarief en afdrukversie (PDF via de browser) - Inbox via IMAP/SMTP, gekoppeld aan contacten - Gebruikers (beheerder/medewerker) en klantportaal (offertes accepteren, bestanden, berichten) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block title %}Import controleren{% endblock %}
|
||||
{% block content %}
|
||||
<form method="post">
|
||||
<input type="hidden" name="kind" value="{{ kind }}">
|
||||
<div class="head">
|
||||
<div><a class="label" href="{{ url_for('import_start') }}">← Ander bestand</a>
|
||||
<h1>{{ filename }}</h1>
|
||||
<div class="muted">{{ total }} rij(en) · {{ {'contacts': 'leads / contactpersonen', 'relations': 'relaties', 'products': 'producten'}[kind] }}</div></div>
|
||||
<div class="actions"><button class="btn">{{ total }} rij(en) importeren</button></div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>Kolommen koppelen</h2>
|
||||
<div class="table-wrap"><table>
|
||||
<thead><tr>
|
||||
{% for col in cols %}
|
||||
<th style="min-width:170px">
|
||||
<div style="margin-bottom:.4rem">{{ col }}</div>
|
||||
<select name="map_{{ loop.index0 }}" aria-label="Doelveld voor {{ col }}">
|
||||
{% for k, l in targets %}<option value="{{ k }}" {{ 'selected' if mapping[loop.index0] == k }}>{{ l }}</option>{% endfor %}
|
||||
</select>
|
||||
</th>
|
||||
{% endfor %}
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
{% for row in rows %}
|
||||
<tr>{% for col in cols %}{% set v = row.get(col) %}<td>{{ (v if v is string else (v|tojson if v is not none else ''))|truncate(60) }}</td>{% endfor %}</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table></div>
|
||||
{% if total > rows|length %}<p class="hint">Eerste {{ rows|length }} van {{ total }} rijen.</p>{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>Opties</h2>
|
||||
<div class="fields">
|
||||
{% if kind == 'contacts' %}
|
||||
<div><label>Importeren als</label><select name="type">{% for k, l in TYPES %}<option value="{{ k }}">{{ l }}</option>{% endfor %}</select></div>
|
||||
<div><label>Status (als de kolom ontbreekt)</label><select name="status">{% for k, l in STATUSES %}<option value="{{ k }}">{{ l }}</option>{% endfor %}</select></div>
|
||||
<div><label>Toewijzen aan</label><select name="assigned_user_id"><option value="">— Niemand —</option>{% for u in USERS %}<option value="{{ u.id }}">{{ u.name }}</option>{% endfor %}</select></div>
|
||||
<div><label>Bron (als de kolom ontbreekt)</label><input name="source" value="Import"></div>
|
||||
{% endif %}
|
||||
{% if kind == 'relations' %}
|
||||
<div><label>Soort</label><select name="relation_kind" id="rkind">{% for k, l in RELATION_KINDS %}<option value="{{ k }}" {{ 'selected' if request.args.get('rkind') == k }}>{{ l }}</option>{% endfor %}</select></div>
|
||||
<div><label>Type (als de kolom ontbreekt)</label>
|
||||
<select name="relation_type"><option value="">—</option>
|
||||
{% for k, l in RELATION_KINDS %}<optgroup label="{{ l }}">{% for t in relation_types[k] %}<option>{{ t }}</option>{% endfor %}</optgroup>{% endfor %}
|
||||
</select></div>
|
||||
{% endif %}
|
||||
{% if kind == 'products' %}
|
||||
<div class="full"><label><input type="checkbox" name="deactivate_missing" value="1">Producten met een SKU die niet in dit bestand staan op inactief zetten (volledige prijslijst)</label>
|
||||
<p class="hint">Alleen als er een kolom aan SKU gekoppeld is. Inactieve producten blijven bestaan, met hun mutaties en offertes.</p></div>
|
||||
{% endif %}
|
||||
<div class="full"><label><input type="checkbox" name="update" value="1" checked>Bestaande {{ 'contacten (zelfde e-mail) aanvullen' if kind == 'contacts' else 'relaties (zelfde naam of KvK) aanvullen' if kind == 'relations' else 'producten bijwerken (zelfde SKU, of zelfde naam als er geen SKU is); alleen gekoppelde kolommen worden gewijzigd' }}; uit = overslaan</label></div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user