470 lines
12 KiB
TypeScript
470 lines
12 KiB
TypeScript
import { PrismaClient } from "@prisma/client";
|
|
import bcrypt from "bcryptjs";
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
const PERMISSIONS: {
|
|
name: string;
|
|
display_name: string;
|
|
module: string;
|
|
description: string;
|
|
}[] = [
|
|
// Docházka
|
|
{
|
|
name: "attendance.record",
|
|
display_name: "Záznam docházky",
|
|
module: "attendance",
|
|
description: "Zapisovat příchody/odchody",
|
|
},
|
|
{
|
|
name: "attendance.history",
|
|
display_name: "Historie docházky",
|
|
module: "attendance",
|
|
description: "Prohlížet vlastní historii docházky",
|
|
},
|
|
{
|
|
name: "attendance.approve",
|
|
display_name: "Schvalování docházky",
|
|
module: "attendance",
|
|
description: "Schvalovat žádosti o dovolenou/nemoc",
|
|
},
|
|
{
|
|
name: "attendance.manage",
|
|
display_name: "Správa docházky",
|
|
module: "attendance",
|
|
description: "Spravovat všechny záznamy, vytvářet/editovat/mazat",
|
|
},
|
|
{
|
|
name: "attendance.balances",
|
|
display_name: "Správa bilancí",
|
|
module: "attendance",
|
|
description: "Spravovat zůstatky dovolené a sick days",
|
|
},
|
|
|
|
// Kniha jízd
|
|
{
|
|
name: "trips.record",
|
|
display_name: "Záznam jízd",
|
|
module: "trips",
|
|
description: "Zapisovat jízdy",
|
|
},
|
|
{
|
|
name: "trips.history",
|
|
display_name: "Historie jízd",
|
|
module: "trips",
|
|
description: "Prohlížet vlastní historii jízd",
|
|
},
|
|
{
|
|
name: "trips.manage",
|
|
display_name: "Správa jízd",
|
|
module: "trips",
|
|
description: "Spravovat všechny jízdy",
|
|
},
|
|
|
|
// Vozidla
|
|
{
|
|
name: "vehicles.manage",
|
|
display_name: "Správa vozidel",
|
|
module: "vehicles",
|
|
description: "Spravovat vozový park",
|
|
},
|
|
|
|
// Nabídky
|
|
{
|
|
name: "offers.view",
|
|
display_name: "Zobrazit nabídky",
|
|
module: "offers",
|
|
description: "Prohlížet seznam nabídek",
|
|
},
|
|
{
|
|
name: "offers.create",
|
|
display_name: "Vytvořit nabídku",
|
|
module: "offers",
|
|
description: "Vytvářet nové nabídky",
|
|
},
|
|
{
|
|
name: "offers.edit",
|
|
display_name: "Upravit nabídku",
|
|
module: "offers",
|
|
description: "Upravovat existující nabídky",
|
|
},
|
|
{
|
|
name: "offers.delete",
|
|
display_name: "Smazat nabídku",
|
|
module: "offers",
|
|
description: "Mazat nabídky",
|
|
},
|
|
{
|
|
name: "offers.export",
|
|
display_name: "Exportovat nabídku",
|
|
module: "offers",
|
|
description: "Exportovat nabídky do PDF",
|
|
},
|
|
|
|
// Objednávky
|
|
{
|
|
name: "orders.view",
|
|
display_name: "Zobrazit objednávky",
|
|
module: "orders",
|
|
description: "Prohlížet seznam objednávek",
|
|
},
|
|
{
|
|
name: "orders.create",
|
|
display_name: "Vytvořit objednávku",
|
|
module: "orders",
|
|
description: "Vytvářet nové objednávky",
|
|
},
|
|
{
|
|
name: "orders.edit",
|
|
display_name: "Upravit objednávku",
|
|
module: "orders",
|
|
description: "Upravovat existující objednávky",
|
|
},
|
|
{
|
|
name: "orders.delete",
|
|
display_name: "Smazat objednávku",
|
|
module: "orders",
|
|
description: "Mazat objednávky",
|
|
},
|
|
{
|
|
name: "orders.export",
|
|
display_name: "Exportovat objednávku",
|
|
module: "orders",
|
|
description: "Exportovat objednávky do PDF",
|
|
},
|
|
|
|
// Faktury
|
|
{
|
|
name: "invoices.view",
|
|
display_name: "Zobrazit faktury",
|
|
module: "invoices",
|
|
description: "Prohlížet seznam faktur",
|
|
},
|
|
{
|
|
name: "invoices.create",
|
|
display_name: "Vytvořit fakturu",
|
|
module: "invoices",
|
|
description: "Vytvářet nové faktury",
|
|
},
|
|
{
|
|
name: "invoices.edit",
|
|
display_name: "Upravit fakturu",
|
|
module: "invoices",
|
|
description: "Upravovat existující faktury",
|
|
},
|
|
{
|
|
name: "invoices.delete",
|
|
display_name: "Smazat fakturu",
|
|
module: "invoices",
|
|
description: "Mazat faktury",
|
|
},
|
|
{
|
|
name: "invoices.export",
|
|
display_name: "Exportovat fakturu",
|
|
module: "invoices",
|
|
description: "Exportovat faktury do PDF",
|
|
},
|
|
|
|
// Projekty
|
|
{
|
|
name: "projects.view",
|
|
display_name: "Zobrazit projekty",
|
|
module: "projects",
|
|
description: "Prohlížet seznam projektů",
|
|
},
|
|
{
|
|
name: "projects.edit",
|
|
display_name: "Upravit projekt",
|
|
module: "projects",
|
|
description: "Upravovat existující projekty",
|
|
},
|
|
{
|
|
name: "projects.delete",
|
|
display_name: "Smazat projekt",
|
|
module: "projects",
|
|
description: "Mazat projekty",
|
|
},
|
|
{
|
|
name: "projects.files",
|
|
display_name: "Soubory projektu",
|
|
module: "projects",
|
|
description: "Spravovat soubory a složky projektu",
|
|
},
|
|
|
|
// Zákazníci
|
|
{
|
|
name: "customers.view",
|
|
display_name: "Zobrazit zákazníky",
|
|
module: "customers",
|
|
description: "Prohlížet seznam zákazníků",
|
|
},
|
|
{
|
|
name: "customers.create",
|
|
display_name: "Vytvořit zákazníka",
|
|
module: "customers",
|
|
description: "Vytvářet nové zákazníky",
|
|
},
|
|
{
|
|
name: "customers.edit",
|
|
display_name: "Upravit zákazníka",
|
|
module: "customers",
|
|
description: "Upravovat existující zákazníky",
|
|
},
|
|
{
|
|
name: "customers.delete",
|
|
display_name: "Smazat zákazníka",
|
|
module: "customers",
|
|
description: "Mazat zákazníky",
|
|
},
|
|
|
|
// Uživatelé
|
|
{
|
|
name: "users.view",
|
|
display_name: "Zobrazit uživatele",
|
|
module: "users",
|
|
description: "Prohlížet seznam uživatelů",
|
|
},
|
|
{
|
|
name: "users.create",
|
|
display_name: "Vytvořit uživatele",
|
|
module: "users",
|
|
description: "Vytvářet nové uživatele",
|
|
},
|
|
{
|
|
name: "users.edit",
|
|
display_name: "Upravit uživatele",
|
|
module: "users",
|
|
description: "Upravovat existující uživatele",
|
|
},
|
|
{
|
|
name: "users.delete",
|
|
display_name: "Smazat uživatele",
|
|
module: "users",
|
|
description: "Mazat uživatele",
|
|
},
|
|
|
|
// Nastavení
|
|
{
|
|
name: "settings.company",
|
|
display_name: "Nastavení společnosti",
|
|
module: "settings",
|
|
description: "Upravovat údaje o společnosti, logo",
|
|
},
|
|
{
|
|
name: "settings.system",
|
|
display_name: "Systémová nastavení",
|
|
module: "settings",
|
|
description: "Spravovat systémová nastavení, 2FA, e-maily, limity",
|
|
},
|
|
{
|
|
name: "settings.banking",
|
|
display_name: "Bankovní účty",
|
|
module: "settings",
|
|
description: "Spravovat bankovní účty společnosti",
|
|
},
|
|
{
|
|
name: "settings.roles",
|
|
display_name: "Role a oprávnění",
|
|
module: "settings",
|
|
description: "Spravovat role a přiřazovat oprávnění",
|
|
},
|
|
{
|
|
name: "settings.templates",
|
|
display_name: "Šablony",
|
|
module: "settings",
|
|
description: "Spravovat šablony nabídek a položek",
|
|
},
|
|
{
|
|
name: "settings.audit",
|
|
display_name: "Audit log",
|
|
module: "settings",
|
|
description: "Prohlížet auditní logy",
|
|
},
|
|
|
|
// Sklad
|
|
{
|
|
name: "warehouse.view",
|
|
display_name: "Zobrazit sklad",
|
|
module: "warehouse",
|
|
description: "Prohlížet stav skladu, položky, reporty a historii pohybů",
|
|
},
|
|
{
|
|
name: "warehouse.operate",
|
|
display_name: "Příjem a výdej",
|
|
module: "warehouse",
|
|
description: "Vytvářet a potvrzovat příjmy, výdeje a rezervace",
|
|
},
|
|
{
|
|
name: "warehouse.manage",
|
|
display_name: "Správa skladu",
|
|
module: "warehouse",
|
|
description: "Spravovat katalog materiálů, dodavatele, lokace a kategorie",
|
|
},
|
|
{
|
|
name: "warehouse.inventory",
|
|
display_name: "Inventura",
|
|
module: "warehouse",
|
|
description: "Vytvářet a potvrzovat inventurní sčítkání",
|
|
},
|
|
];
|
|
|
|
async function main() {
|
|
console.log("Seeding permissions...");
|
|
|
|
// 1. Clear existing permissions and re-insert current set
|
|
await prisma.role_permissions.deleteMany({});
|
|
await prisma.permissions.deleteMany({});
|
|
console.log(" Cleared old permissions");
|
|
|
|
for (const perm of PERMISSIONS) {
|
|
await prisma.permissions.create({ data: perm });
|
|
}
|
|
console.log(` Inserted ${PERMISSIONS.length} permissions`);
|
|
|
|
// 2. Ensure admin role exists
|
|
let adminRole = await prisma.roles.findFirst({ where: { name: "admin" } });
|
|
if (!adminRole) {
|
|
adminRole = await prisma.roles.create({
|
|
data: {
|
|
name: "admin",
|
|
display_name: "Administrátor",
|
|
description: "Hlavní administrátor s plným přístupem",
|
|
},
|
|
});
|
|
console.log(" Created admin role");
|
|
} else {
|
|
console.log(" Admin role already exists (id=" + adminRole.id + ")");
|
|
}
|
|
|
|
// 3. Assign all permissions to admin role
|
|
const allPerms = await prisma.permissions.findMany();
|
|
const existingAssignments = await prisma.role_permissions.findMany({
|
|
where: { role_id: adminRole.id },
|
|
});
|
|
|
|
// Delete stale assignments (permissions no longer in the list)
|
|
const validIds = new Set(allPerms.map((p) => p.id));
|
|
const staleIds = existingAssignments.filter(
|
|
(a) => !validIds.has(a.permission_id),
|
|
);
|
|
if (staleIds.length > 0) {
|
|
for (const s of staleIds) {
|
|
await prisma.role_permissions.delete({
|
|
where: {
|
|
role_id_permission_id: {
|
|
role_id: adminRole.id,
|
|
permission_id: s.permission_id,
|
|
},
|
|
},
|
|
});
|
|
}
|
|
console.log(` Removed ${staleIds.length} stale role_permissions`);
|
|
}
|
|
|
|
// Add missing assignments
|
|
const existingIds = new Set(existingAssignments.map((a) => a.permission_id));
|
|
let added = 0;
|
|
for (const perm of allPerms) {
|
|
if (!existingIds.has(perm.id)) {
|
|
await prisma.role_permissions.create({
|
|
data: { role_id: adminRole.id, permission_id: perm.id },
|
|
});
|
|
added++;
|
|
}
|
|
}
|
|
if (added > 0) console.log(` Added ${added} role_permission assignments`);
|
|
console.log(` Admin role now has all ${allPerms.length} permissions`);
|
|
|
|
// 4. Ensure admin user exists
|
|
let adminUser = await prisma.users.findFirst({
|
|
where: { username: "admin" },
|
|
});
|
|
if (!adminUser) {
|
|
const hash = bcrypt.hashSync("admin", 10);
|
|
adminUser = await prisma.users.create({
|
|
data: {
|
|
username: "admin",
|
|
email: "admin@boha.local",
|
|
password_hash: hash,
|
|
first_name: "Admin",
|
|
last_name: "BOHA",
|
|
role_id: adminRole.id,
|
|
is_active: true,
|
|
},
|
|
});
|
|
console.log(" Created admin user (admin / admin)");
|
|
} else if (adminUser.role_id !== adminRole.id) {
|
|
await prisma.users.update({
|
|
where: { id: adminUser.id },
|
|
data: { role_id: adminRole.id },
|
|
});
|
|
console.log(" Updated admin user role_id to admin role");
|
|
} else {
|
|
console.log(" Admin user already exists with correct role");
|
|
}
|
|
|
|
// 5. Create default company_settings if not exists
|
|
const existingSettings = await prisma.company_settings.findFirst();
|
|
if (!existingSettings) {
|
|
await prisma.company_settings.create({
|
|
data: {
|
|
company_name: "BOHA s.r.o.",
|
|
default_currency: "CZK",
|
|
default_vat_rate: 21.0,
|
|
available_vat_rates: JSON.stringify([0, 10, 15, 21]),
|
|
available_currencies: JSON.stringify(["CZK", "EUR"]),
|
|
offer_number_pattern: "NAB-{YYYY}-{NNN}",
|
|
order_number_pattern: "OBJ-{YYYY}-{NNN}",
|
|
invoice_number_pattern: "FV-{YYYY}-{NNN}",
|
|
break_threshold_hours: 6.0,
|
|
break_duration_short: 15,
|
|
break_duration_long: 30,
|
|
clock_rounding_minutes: 15,
|
|
require_2fa: false,
|
|
max_login_attempts: 5,
|
|
lockout_minutes: 15,
|
|
max_requests_per_minute: 300,
|
|
},
|
|
});
|
|
console.log(" Created default company_settings");
|
|
} else {
|
|
console.log(" company_settings already exists");
|
|
}
|
|
|
|
// 6. Initialize number_sequences for current year
|
|
const year = new Date().getFullYear();
|
|
const types = [
|
|
"quotation",
|
|
"order",
|
|
"invoice",
|
|
"warehouse_receipt",
|
|
"warehouse_issue",
|
|
"warehouse_inventory",
|
|
];
|
|
for (const type of types) {
|
|
const existing = await prisma.number_sequences.findFirst({
|
|
where: { type, year },
|
|
});
|
|
if (!existing) {
|
|
await prisma.number_sequences.create({
|
|
data: { type, year, last_number: 0 },
|
|
});
|
|
console.log(` Created number_sequence: ${type}/${year}`);
|
|
}
|
|
}
|
|
console.log(" number_sequences ready");
|
|
|
|
console.log(
|
|
"\nSeed complete — " +
|
|
PERMISSIONS.length +
|
|
" permissions, 1 admin role, company_settings + number_sequences ready.",
|
|
);
|
|
}
|
|
|
|
main()
|
|
.catch((e) => {
|
|
console.error("Seed failed:", e);
|
|
process.exit(1);
|
|
})
|
|
.finally(() => prisma.$disconnect());
|