Files
assetsTracker/scripts/seed-dummy-data.js
2026-03-19 21:13:55 +01:00

272 lines
10 KiB
JavaScript

/**
* Erstellt Dummy-Daten: eine Dummy-Filiale mit Mitarbeitern, Lagerstandorten und Geräten.
* Voraussetzung: npm run setup bereits ausgeführt (Collections existieren).
*
* Ausführung: node scripts/seed-dummy-data.js
*/
import { Client, Databases, Users, Teams, ID, Query } from 'node-appwrite';
import { readFileSync } from 'fs';
import { resolve, dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
function loadEnv() {
const envPath = resolve(__dirname, '..', '.env');
try {
const lines = readFileSync(envPath, 'utf-8').split('\n');
for (const line of lines) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith('#')) continue;
const eqIdx = trimmed.indexOf('=');
if (eqIdx === -1) continue;
const key = trimmed.slice(0, eqIdx).trim();
const value = trimmed.slice(eqIdx + 1).trim();
process.env[key] = value;
}
} catch {
console.error('Fehler: .env nicht gefunden. Bitte .env aus .env.example anlegen.');
process.exit(1);
}
}
loadEnv();
const ENDPOINT = process.env.APPWRITE_ENDPOINT;
const PROJECT_ID = process.env.VITE_APPWRITE_PROJECT_ID;
const API_KEY = process.env.APPWRITE_API_KEY;
const DATABASE_ID = process.env.VITE_APPWRITE_DATABASE_ID || 'defekttrack_db';
const DUMMY_PASSWORD = 'Dummy1234!';
if (!ENDPOINT || !PROJECT_ID || !API_KEY || API_KEY === 'YOUR_API_KEY_HERE') {
console.error('Bitte APPWRITE_ENDPOINT, VITE_APPWRITE_PROJECT_ID und APPWRITE_API_KEY in .env setzen.');
process.exit(1);
}
const client = new Client()
.setEndpoint(ENDPOINT)
.setProject(PROJECT_ID)
.setKey(API_KEY);
const databases = new Databases(client);
const users = new Users(client);
const teams = new Teams(client);
/** Prüft ob die Dummy-Filiale bereits existiert */
async function getOrCreateDummyLocation() {
const res = await databases.listDocuments(DATABASE_ID, 'locations', [
Query.equal('name', ['Dummy-Filiale München']),
Query.limit(1),
]);
if (res.documents.length > 0) {
console.log(`Dummy-Filiale existiert bereits: "${res.documents[0].name}" (${res.documents[0].$id})`);
return res.documents[0];
}
const loc = await databases.createDocument(DATABASE_ID, 'locations', ID.unique(), {
name: 'Dummy-Filiale München',
address: 'Musterstraße 42, 80331 München',
isActive: true,
});
console.log(`Filiale erstellt: "${loc.name}" (${loc.$id})`);
return loc;
}
/** Erstellt oder findet einen Appwrite-User und users_meta */
async function ensureUser(email, name, role, locationId) {
let userId;
const metaCheck = await databases.listDocuments(DATABASE_ID, 'users_meta', [
Query.equal('userName', [name]),
Query.equal('locationId', [locationId]),
Query.limit(1),
]);
if (metaCheck.documents.length > 0) {
userId = metaCheck.documents[0].userId;
const userCheck = await users.get(userId).catch(() => null);
if (userCheck) {
console.log(` User existiert: ${name} (${email})`);
return userId;
}
}
try {
const user = await users.create(ID.unique(), email, undefined, DUMMY_PASSWORD, name);
userId = user.$id;
console.log(` User erstellt: ${name} (${email})`);
} catch (err) {
if (err.code === 409) {
const list = await users.list([Query.equal('email', [email])]);
if (list.users.length > 0) {
userId = list.users[0].$id;
console.log(` User existiert: ${name}`);
} else throw err;
} else throw err;
}
try {
await teams.createMembership(role, [], email, userId, undefined, `${ENDPOINT}/auth/confirm`);
} catch (err) {
if (err.code !== 409) console.warn(` Team ${role}:`, err.message);
}
const existingMeta = await databases.listDocuments(DATABASE_ID, 'users_meta', [
Query.equal('userId', [userId]),
Query.limit(1),
]);
if (existingMeta.documents.length === 0) {
await databases.createDocument(DATABASE_ID, 'users_meta', ID.unique(), {
userId,
locationId,
userName: name,
role,
mustChangePassword: false,
});
console.log(` users_meta erstellt für ${name}`);
}
return userId;
}
/** Erstellt Lagerstandorte für die Filiale, gibt alle zurück */
async function createLagerstandorte(locationId) {
const names = ['Lager A - EG', 'Lager B - Keller', 'Reparaturwerkstatt'];
const existing = await databases.listDocuments(DATABASE_ID, 'lagerstandorte', [
Query.equal('locationId', [locationId]),
Query.limit(20),
]);
const existingNames = new Set(existing.documents.map((d) => d.name));
for (const name of names) {
if (existingNames.has(name)) {
console.log(` Lagerstandort existiert: ${name}`);
continue;
}
await databases.createDocument(DATABASE_ID, 'lagerstandorte', ID.unique(), {
name,
locationId,
isActive: true,
});
existingNames.add(name);
console.log(` Lagerstandort erstellt: ${name}`);
}
const res = await databases.listDocuments(DATABASE_ID, 'lagerstandorte', [
Query.equal('locationId', [locationId]),
Query.limit(20),
]);
return res.documents;
}
/** Erstellt Dummy-Mitarbeiter */
async function createDummyMitarbeiter(locationId) {
const mitarbeiter = [
{ email: 'dummy-filialleiter@defekttrack.local', name: 'Max Mustermann', role: 'filialleiter' },
{ email: 'dummy-service1@defekttrack.local', name: 'Lisa Schmidt', role: 'service' },
{ email: 'dummy-service2@defekttrack.local', name: 'Thomas Weber', role: 'service' },
{ email: 'dummy-service3@defekttrack.local', name: 'Anna Becker', role: 'service' },
{ email: 'dummy-lager@defekttrack.local', name: 'Peter Krause', role: 'lager' },
];
const userNames = [];
for (const m of mitarbeiter) {
await ensureUser(m.email, m.name, m.role, locationId);
userNames.push(m.name);
await new Promise((r) => setTimeout(r, 300));
}
return userNames;
}
/** Erstellt Dummy-Geräte (Assets) */
async function createDummyAssets(locationId, lagerstandorte, userNames) {
const statuses = ['offen', 'in_bearbeitung', 'entsorgt'];
const prioritaeten = ['hoch', 'mittel', 'niedrig'];
const geraete = [
{ erl: 'ERL-001', serien: 'SN-100001', artikel: 'ART-101', bezeichnung: 'Laptop Dell Latitude 5520', defekt: 'Display defekt' },
{ erl: 'ERL-002', serien: 'SN-100002', artikel: 'ART-102', bezeichnung: 'Monitor LG 27"', defekt: 'Kein Bild' },
{ erl: 'ERL-003', serien: 'SN-100003', artikel: 'ART-103', bezeichnung: 'Tastatur Logitech MX', defekt: 'Tasten kleben' },
{ erl: 'ERL-004', serien: 'SN-100004', artikel: 'ART-104', bezeichnung: 'Maus Microsoft', defekt: 'Scroller defekt' },
{ erl: 'ERL-005', serien: 'SN-100005', artikel: 'ART-105', bezeichnung: 'Drucker HP LaserJet', defekt: 'Papierstau' },
{ erl: 'ERL-006', serien: 'SN-100006', artikel: 'ART-106', bezeichnung: 'Router Cisco', defekt: 'Keine Verbindung' },
{ erl: 'ERL-007', serien: 'SN-100007', artikel: 'ART-107', bezeichnung: 'Smartphone Samsung', defekt: 'Akku schwach' },
{ erl: 'ERL-008', serien: 'SN-100008', artikel: 'ART-108', bezeichnung: 'Tablet iPad', defekt: 'Display Riss' },
{ erl: 'ERL-009', serien: 'SN-100009', artikel: 'ART-109', bezeichnung: 'Switch Netgear', defekt: 'LED defekt' },
{ erl: 'ERL-010', serien: 'SN-100010', artikel: 'ART-110', bezeichnung: 'Festplatte SSD 1TB', defekt: 'Lesefehler' },
{ erl: 'ERL-011', serien: 'SN-100011', artikel: 'ART-111', bezeichnung: 'USB-Hub 4-Port', defekt: 'Port 3 defekt' },
{ erl: 'ERL-012', serien: 'SN-100012', artikel: 'ART-112', bezeichnung: 'Webcam Logitech', defekt: 'Mikrofon rauscht' },
{ erl: 'ERL-013', serien: 'SN-100013', artikel: 'ART-113', bezeichnung: 'Headset Jabra', defekt: 'Kabelbruch' },
{ erl: 'ERL-014', serien: 'SN-100014', artikel: 'ART-114', bezeichnung: 'Kabel HDMI 2m', defekt: 'Kontakt defekt' },
{ erl: 'ERL-015', serien: 'SN-100015', artikel: 'ART-115', bezeichnung: 'Laptop Lenovo ThinkPad', defekt: 'Lüfter laut' },
];
const existing = await databases.listDocuments(DATABASE_ID, 'assets', [
Query.startsWith('erlNummer', ['ERL-00']),
Query.limit(50),
]);
const existingErl = new Set(existing.documents.map((d) => d.erlNummer));
let created = 0;
for (let i = 0; i < geraete.length; i++) {
const g = geraete[i];
if (existingErl.has(g.erl)) continue;
const ls = lagerstandorte[i % lagerstandorte.length];
const zustaendig = userNames[i % userNames.length];
const status = statuses[i % statuses.length];
const prio = prioritaeten[i % prioritaeten.length];
await databases.createDocument(DATABASE_ID, 'assets', ID.unique(), {
erlNummer: g.erl,
seriennummer: g.serien,
artikelNr: g.artikel,
bezeichnung: g.bezeichnung,
defekt: g.defekt,
lagerstandortId: ls?.$id || '',
zustaendig,
status,
prio,
kommentar: i % 3 === 0 ? 'Dummy-Eintrag für Testzwecke' : '',
createdBy: 'Seed-Script',
lastEditedBy: 'Seed-Script',
});
created++;
console.log(` Gerät erstellt: ${g.erl} (${g.bezeichnung}) - ${status}`);
if (created % 3 === 0) await new Promise((r) => setTimeout(r, 200));
}
if (created === 0) console.log(' Alle Dummy-Geräte existieren bereits.');
return created;
}
async function main() {
console.log('=== DefektTrack Dummy-Daten Seed ===');
console.log('');
const loc = await getOrCreateDummyLocation();
const locationId = loc.$id;
console.log('');
console.log('--- Dummy-Mitarbeiter ---');
const userNames = await createDummyMitarbeiter(locationId);
console.log('');
console.log('--- Lagerstandorte ---');
const lsList = await createLagerstandorte(locationId);
console.log('');
console.log('--- Dummy-Geräte ---');
await createDummyAssets(locationId, lsList, userNames);
console.log('');
console.log('=== Dummy-Daten Seed abgeschlossen ===');
console.log('');
console.log('Filiale: Dummy-Filiale München');
console.log('Mitarbeiter-Logins (Passwort: Dummy1234!):');
console.log(' - dummy-filialleiter@defekttrack.local (Max Mustermann, Filialleiter)');
console.log(' - dummy-service1@defekttrack.local (Lisa Schmidt)');
console.log(' - dummy-service2@defekttrack.local (Thomas Weber)');
console.log(' - dummy-service3@defekttrack.local (Anna Becker)');
console.log(' - dummy-lager@defekttrack.local (Peter Krause)');
console.log('');
}
main().catch((err) => {
console.error('Seed fehlgeschlagen:', err);
process.exit(1);
});