272 lines
10 KiB
JavaScript
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);
|
|
});
|