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:
+160
@@ -0,0 +1,160 @@
|
||||
CREATE TABLE IF NOT EXISTS settings (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
email TEXT NOT NULL UNIQUE COLLATE NOCASE,
|
||||
password_hash TEXT NOT NULL,
|
||||
role TEXT NOT NULL DEFAULT 'user',
|
||||
active INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
-- Relaties (zoals accounts in EspoCRM): klantbundels (huishouden, familie, bedrijf) en partners
|
||||
-- (leverancier, aannemer, ...). Contactpersonen hangen eronder met een rol.
|
||||
CREATE TABLE IF NOT EXISTS relations (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
kind TEXT NOT NULL DEFAULT 'klant',
|
||||
type TEXT DEFAULT '',
|
||||
name TEXT NOT NULL,
|
||||
email TEXT DEFAULT '',
|
||||
phone TEXT DEFAULT '',
|
||||
website TEXT DEFAULT '',
|
||||
address TEXT DEFAULT '',
|
||||
postcode TEXT DEFAULT '',
|
||||
city TEXT DEFAULT '',
|
||||
kvk TEXT DEFAULT '',
|
||||
notes TEXT DEFAULT '',
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_relations_name ON relations(kind, name COLLATE NOCASE);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS contacts (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL DEFAULT '',
|
||||
email TEXT DEFAULT '',
|
||||
phone TEXT DEFAULT '',
|
||||
company TEXT DEFAULT '',
|
||||
address TEXT DEFAULT '',
|
||||
postcode TEXT DEFAULT '',
|
||||
city TEXT DEFAULT '',
|
||||
type TEXT NOT NULL DEFAULT 'lead',
|
||||
status TEXT NOT NULL DEFAULT 'nieuw',
|
||||
source TEXT DEFAULT '',
|
||||
value REAL NOT NULL DEFAULT 0,
|
||||
assigned_user_id INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
||||
relation_id INTEGER REFERENCES relations(id) ON DELETE SET NULL,
|
||||
relation_role TEXT DEFAULT '',
|
||||
portal_token TEXT,
|
||||
portal_password_hash TEXT,
|
||||
portal_last_login TEXT,
|
||||
notes TEXT DEFAULT '',
|
||||
extra TEXT DEFAULT '{}',
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_contacts_email ON contacts(email COLLATE NOCASE);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS activities (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
contact_id INTEGER NOT NULL REFERENCES contacts(id) ON DELETE CASCADE,
|
||||
type TEXT NOT NULL,
|
||||
body TEXT DEFAULT '',
|
||||
user_id INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
||||
created_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS files (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
contact_id INTEGER REFERENCES contacts(id) ON DELETE CASCADE,
|
||||
stored TEXT NOT NULL,
|
||||
original TEXT NOT NULL,
|
||||
mime TEXT DEFAULT '',
|
||||
size INTEGER DEFAULT 0,
|
||||
created_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS products (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
sku TEXT DEFAULT '',
|
||||
description TEXT DEFAULT '',
|
||||
unit TEXT DEFAULT 'stuk',
|
||||
supplier TEXT DEFAULT '',
|
||||
supplier_id INTEGER REFERENCES relations(id) ON DELETE SET NULL,
|
||||
price REAL NOT NULL DEFAULT 0,
|
||||
vat REAL NOT NULL DEFAULT 21,
|
||||
image TEXT DEFAULT '',
|
||||
active INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT
|
||||
);
|
||||
|
||||
-- Elke wijziging aan een product (handmatig, import of API), zodat prijsmutaties terug te zien zijn.
|
||||
CREATE TABLE IF NOT EXISTS product_history (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
product_id INTEGER NOT NULL REFERENCES products(id) ON DELETE CASCADE,
|
||||
field TEXT NOT NULL,
|
||||
old_value TEXT,
|
||||
new_value TEXT,
|
||||
source TEXT DEFAULT '',
|
||||
user_id INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
||||
created_at TEXT NOT NULL
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_product_history ON product_history(product_id, created_at);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS quotes (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
number TEXT UNIQUE NOT NULL,
|
||||
contact_id INTEGER REFERENCES contacts(id) ON DELETE SET NULL,
|
||||
status TEXT NOT NULL DEFAULT 'concept',
|
||||
title TEXT DEFAULT '',
|
||||
date TEXT NOT NULL,
|
||||
valid_until TEXT,
|
||||
intro TEXT DEFAULT '',
|
||||
notes TEXT DEFAULT '',
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS quote_lines (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
quote_id INTEGER NOT NULL REFERENCES quotes(id) ON DELETE CASCADE,
|
||||
position INTEGER NOT NULL DEFAULT 0,
|
||||
product_id INTEGER,
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
qty REAL NOT NULL DEFAULT 1,
|
||||
unit TEXT DEFAULT '',
|
||||
price REAL NOT NULL DEFAULT 0,
|
||||
vat REAL NOT NULL DEFAULT 21
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS emails (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
uid TEXT UNIQUE,
|
||||
message_id TEXT DEFAULT '',
|
||||
direction TEXT NOT NULL DEFAULT 'in',
|
||||
contact_id INTEGER REFERENCES contacts(id) ON DELETE SET NULL,
|
||||
from_name TEXT DEFAULT '',
|
||||
from_addr TEXT DEFAULT '',
|
||||
to_addr TEXT DEFAULT '',
|
||||
subject TEXT DEFAULT '',
|
||||
body TEXT DEFAULT '',
|
||||
date TEXT NOT NULL,
|
||||
is_read INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_emails_from ON emails(from_addr);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tasks (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
contact_id INTEGER REFERENCES contacts(id) ON DELETE CASCADE,
|
||||
user_id INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
||||
title TEXT NOT NULL,
|
||||
due_date TEXT,
|
||||
done INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TEXT NOT NULL
|
||||
);
|
||||
Reference in New Issue
Block a user