ADD: added admin panel and archiv mandates
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
-- Add UserRole enum (MySQL ENUM)
|
||||
ALTER TABLE `users` ADD COLUMN `username` VARCHAR(191) NULL;
|
||||
ALTER TABLE `users` ADD COLUMN `role` ENUM('USER', 'ADMIN') NOT NULL DEFAULT 'USER';
|
||||
|
||||
-- Backfill username from email (use part before @, ensure uniqueness)
|
||||
UPDATE `users` SET `username` = LOWER(SUBSTRING_INDEX(`email`, '@', 1)) WHERE `username` IS NULL;
|
||||
|
||||
-- Make username NOT NULL and add unique constraint
|
||||
ALTER TABLE `users` MODIFY COLUMN `username` VARCHAR(191) NOT NULL;
|
||||
ALTER TABLE `users` ADD UNIQUE INDEX `users_username_key`(`username`);
|
||||
|
||||
-- Create AuditLog table
|
||||
CREATE TABLE `audit_logs` (
|
||||
`id` VARCHAR(191) NOT NULL,
|
||||
`userId` VARCHAR(191) NULL,
|
||||
`action` VARCHAR(191) NOT NULL,
|
||||
`entity` VARCHAR(191) NULL,
|
||||
`entityId` VARCHAR(191) NULL,
|
||||
`metadata` JSON NULL,
|
||||
`ipAddress` VARCHAR(191) NULL,
|
||||
`createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
|
||||
INDEX `audit_logs_userId_idx`(`userId`),
|
||||
INDEX `audit_logs_createdAt_idx`(`createdAt`),
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- Add foreign key from audit_logs to users
|
||||
ALTER TABLE `audit_logs` ADD CONSTRAINT `audit_logs_userId_fkey` FOREIGN KEY (`userId`) REFERENCES `users`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,2 @@
|
||||
-- Extend InvoiceStatus enum with ARCHIVED
|
||||
ALTER TABLE `invoices` MODIFY COLUMN `status` ENUM('DRAFT', 'SENT', 'PAID', 'CANCELLED', 'ARCHIVED') NOT NULL DEFAULT 'DRAFT';
|
||||
@@ -0,0 +1,7 @@
|
||||
-- Rename ARCHIVED -> DELETED in InvoiceStatus enum
|
||||
ALTER TABLE `invoices` MODIFY COLUMN `status` ENUM('DRAFT', 'SENT', 'PAID', 'CANCELLED', 'DELETED') NOT NULL DEFAULT 'DRAFT';
|
||||
|
||||
-- Add archived fields to companies
|
||||
ALTER TABLE `companies`
|
||||
ADD COLUMN `archived` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
ADD COLUMN `archivedAt` DATETIME(3) NULL;
|
||||
+31
-4
@@ -8,18 +8,42 @@ datasource db {
|
||||
shadowDatabaseUrl = env("SHADOW_DATABASE_URL")
|
||||
}
|
||||
|
||||
enum UserRole {
|
||||
USER
|
||||
ADMIN
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
email String @unique
|
||||
id String @id @default(cuid())
|
||||
email String @unique
|
||||
username String @unique
|
||||
passwordHash String
|
||||
name String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
role UserRole @default(USER)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
companies Company[]
|
||||
auditLogs AuditLog[]
|
||||
|
||||
@@map("users")
|
||||
}
|
||||
|
||||
model AuditLog {
|
||||
id String @id @default(cuid())
|
||||
userId String?
|
||||
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
|
||||
action String
|
||||
entity String?
|
||||
entityId String?
|
||||
metadata Json?
|
||||
ipAddress String?
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([userId])
|
||||
@@index([createdAt])
|
||||
@@map("audit_logs")
|
||||
}
|
||||
|
||||
model Company {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
@@ -39,6 +63,8 @@ model Company {
|
||||
invoicePrefix String @default("RE")
|
||||
invoiceSequence Int @default(0)
|
||||
kleinunternehmer Boolean @default(false)
|
||||
archived Boolean @default(false)
|
||||
archivedAt DateTime?
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
customers Customer[]
|
||||
@@ -97,6 +123,7 @@ enum InvoiceStatus {
|
||||
SENT
|
||||
PAID
|
||||
CANCELLED
|
||||
DELETED
|
||||
}
|
||||
|
||||
model InvoiceItem {
|
||||
|
||||
+37
-1
@@ -13,11 +13,13 @@ async function main() {
|
||||
update: {},
|
||||
create: {
|
||||
email: "anna@example.de",
|
||||
username: "anna",
|
||||
passwordHash,
|
||||
name: "Anna Musterfrau",
|
||||
role: "ADMIN",
|
||||
},
|
||||
});
|
||||
console.log(`✓ User created: ${user.email}`);
|
||||
console.log(`✓ User created: ${user.email} (username: ${user.username}, role: ${user.role})`);
|
||||
|
||||
// Create demo company
|
||||
const company = await prisma.company.upsert({
|
||||
@@ -94,6 +96,40 @@ async function main() {
|
||||
});
|
||||
console.log(`✓ Invoice created: ${invoice.number}`);
|
||||
|
||||
const invoice2 = await prisma.invoice.upsert({
|
||||
where: { id: "demo-invoice-2" },
|
||||
update: {},
|
||||
create: {
|
||||
id: "demo-invoice-2",
|
||||
number: "RE-2024-002",
|
||||
companyId: company.id,
|
||||
customerId: customer.id,
|
||||
issueDate: new Date("2026-02-15"),
|
||||
deliveryDate: new Date("2026-02-15"),
|
||||
dueDate: new Date("2026-03-14"),
|
||||
status: "PAID",
|
||||
netTotal: 2000.0,
|
||||
taxTotal: 380.0,
|
||||
grossTotal: 2380.0,
|
||||
items: {
|
||||
create: [
|
||||
{
|
||||
position: 1,
|
||||
description: "Buchhaltungsleistungen Februar 2024",
|
||||
quantity: 10,
|
||||
unit: "h",
|
||||
unitPrice: 200.0,
|
||||
taxRate: 19.0,
|
||||
netAmount: 2000.0,
|
||||
taxAmount: 380.0,
|
||||
grossAmount: 2380.0,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
console.log(`✓ Invoice created: ${invoice2.number}`);
|
||||
|
||||
// Update company sequence
|
||||
await prisma.company.update({
|
||||
where: { id: company.id },
|
||||
|
||||
Reference in New Issue
Block a user