Files
app/prisma/schema.prisma
BOHA aa6c1b5094 refactor: fix all Low findings from FLAWS_REPORT audit
- Auth: TOTP params from config, JWT error logging, audit log failure
  logging, replaced_by_hash validation on token rotation
- Invoices: remove dead VAT code, consistent PDF permissions,
  WebP magic-byte detection, deduped exchange-rate fetches
- Orders/Offers: multipart limit from config, use paginated() helper,
  payment method from DB in PDF
- Projects: verify project exists before creating note
- Attendance: action_type enum validation, consistent local-time
  shift_date construction, holiday attendance in work fund,
  trips.view permission on last-km query
- Users: paginated() helper usage, remove duplicate dashboard keys,
  parallel currency conversion, single hashToken implementation
- Frontend: memoized customInput, reliable print onload, modal prop
  standardization (isOpen), ConfirmModal type icons, id===0 key
  fallback, Login useCallback, CompanySettings ConfirmModal,
  Attendance timeout cleanup, Dashboard memoization, beforeunload
  dirty-state warnings on Invoice/Offer/Order detail
- Schema: invoice_alert_log timestamp, config/env comment on
  Date.prototype.toJSON override
- Utils: exchange-rate inflight dedup

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-24 08:45:37 +02:00

650 lines
29 KiB
Plaintext

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model attendance {
id Int @id @default(autoincrement())
user_id Int
shift_date DateTime @db.Date
arrival_time DateTime? @db.DateTime(0)
arrival_lat Decimal? @db.Decimal(10, 8)
arrival_lng Decimal? @db.Decimal(11, 8)
arrival_accuracy Decimal? @db.Decimal(10, 2)
arrival_address String? @db.VarChar(500)
break_start DateTime? @db.DateTime(0)
break_end DateTime? @db.DateTime(0)
departure_time DateTime? @db.DateTime(0)
departure_lat Decimal? @db.Decimal(10, 8)
departure_lng Decimal? @db.Decimal(11, 8)
departure_accuracy Decimal? @db.Decimal(10, 2)
departure_address String? @db.VarChar(500)
notes String? @db.Text
project_id Int?
leave_type attendance_leave_type? @default(work)
leave_hours Decimal? @db.Decimal(4, 2)
created_at DateTime? @default(now()) @db.Timestamp(0)
updated_at DateTime? @default(now()) @db.Timestamp(0)
users users @relation(fields: [user_id], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "attendance_ibfk_1")
attendance_project_logs attendance_project_logs[]
@@unique([user_id, shift_date], map: "idx_attendance_user_date")
@@index([user_id, departure_time], map: "idx_attendance_user_departure")
@@index([project_id], map: "idx_project_id")
}
model attendance_project_logs {
id Int @id @default(autoincrement())
attendance_id Int
project_id Int
started_at DateTime? @db.DateTime(0)
ended_at DateTime? @db.DateTime(0)
hours Int? @db.UnsignedInt
minutes Int? @db.UnsignedInt
attendance attendance @relation(fields: [attendance_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
projects projects? @relation(fields: [project_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@index([attendance_id], map: "idx_attendance_project_logs_aid")
@@index([project_id], map: "idx_project_id")
@@index([started_at], map: "idx_started_at")
}
model audit_logs {
id Int @id @default(autoincrement())
user_id Int?
username String? @db.VarChar(100)
user_ip String? @db.VarChar(45)
action String @db.VarChar(100)
entity_type String? @db.VarChar(50)
entity_id Int?
description String? @db.Text
old_values String? @db.LongText
new_values String? @db.LongText
user_agent String? @db.Text
session_id String? @db.VarChar(128)
created_at DateTime? @default(now()) @db.Timestamp(0)
@@index([created_at], map: "idx_audit_log_created")
@@index([action], map: "idx_audit_logs_action")
@@index([created_at], map: "idx_audit_logs_created")
@@index([entity_type, entity_id, created_at], map: "idx_audit_logs_entity")
@@index([user_id, created_at], map: "idx_audit_logs_user_created")
@@fulltext([description], map: "idx_audit_search")
}
model bank_accounts {
id Int @id @default(autoincrement())
account_name String? @db.VarChar(255)
bank_name String? @db.VarChar(255)
account_number String? @db.VarChar(50)
iban String? @db.VarChar(50)
bic String? @db.VarChar(20)
currency String? @default("CZK") @db.VarChar(10)
is_default Boolean? @default(false)
position Int? @default(0)
created_at DateTime? @default(now()) @db.DateTime(0)
modified_at DateTime? @db.DateTime(0)
}
model company_settings {
id Int @id @default(autoincrement())
company_name String? @db.VarChar(255)
street String? @db.VarChar(255)
city String? @db.VarChar(255)
postal_code String? @db.VarChar(20)
country String? @db.VarChar(100)
company_id String? @db.VarChar(50)
vat_id String? @db.VarChar(50)
custom_fields String? @db.LongText
logo_data Bytes?
logo_data_dark Bytes?
quotation_prefix String? @db.VarChar(20)
default_currency String? @default("CZK") @db.VarChar(10)
default_vat_rate Decimal? @default(21.00) @db.Decimal(5, 2)
uuid String? @unique @db.VarChar(36)
modified_at DateTime? @db.DateTime(0)
is_deleted Boolean? @default(false)
sync_version Int? @default(0)
order_type_code String? @db.VarChar(10)
invoice_type_code String? @db.VarChar(10)
require_2fa Boolean @default(false)
break_threshold_hours Decimal? @default(6) @db.Decimal(4, 2)
break_duration_short Int? @default(15)
break_duration_long Int? @default(30)
clock_rounding_minutes Int? @default(15)
invoice_alert_email String? @db.VarChar(255)
leave_notify_email String? @db.VarChar(255)
max_login_attempts Int? @default(5)
lockout_minutes Int? @default(15)
max_requests_per_minute Int? @default(300)
available_vat_rates String? @db.LongText
available_currencies String? @db.LongText
smtp_from String? @db.VarChar(255)
smtp_from_name String? @db.VarChar(255)
offer_number_pattern String? @db.VarChar(100)
order_number_pattern String? @db.VarChar(100)
invoice_number_pattern String? @db.VarChar(100)
}
model customers {
id Int @id @default(autoincrement())
name String @db.VarChar(255)
street String? @db.VarChar(255)
city String? @db.VarChar(255)
postal_code String? @db.VarChar(20)
country String? @db.VarChar(100)
company_id String? @db.VarChar(50)
vat_id String? @db.VarChar(50)
custom_fields String? @db.LongText
created_at DateTime? @default(now()) @db.DateTime(0)
uuid String? @db.VarChar(36)
modified_at DateTime? @db.DateTime(0)
sync_version Int? @default(0)
invoices invoices[]
orders orders[]
projects projects[]
quotations quotations[]
}
model invoice_items {
id Int @id @default(autoincrement())
invoice_id Int
description String? @db.VarChar(500)
quantity Decimal? @default(1.000) @db.Decimal(12, 3)
unit String? @db.VarChar(20)
unit_price Decimal? @default(0.00) @db.Decimal(12, 2)
vat_rate Decimal? @default(21.00) @db.Decimal(5, 2)
position Int? @default(0)
invoices invoices @relation(fields: [invoice_id], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "invoice_items_ibfk_1")
@@index([invoice_id], map: "invoice_id")
}
model invoices {
id Int @id @default(autoincrement())
invoice_number String? @unique(map: "idx_invoices_number_unique") @db.VarChar(50)
order_id Int?
customer_id Int?
status String? @default("issued") @db.VarChar(30)
currency String? @default("CZK") @db.VarChar(10)
vat_rate Decimal? @default(21.00) @db.Decimal(5, 2)
apply_vat Boolean? @default(true)
payment_method String? @db.VarChar(50)
constant_symbol String? @db.VarChar(20)
bank_name String? @db.VarChar(255)
bank_swift String? @db.VarChar(20)
bank_iban String? @db.VarChar(50)
bank_account String? @db.VarChar(50)
issue_date DateTime? @db.Date
due_date DateTime? @db.Date
tax_date DateTime? @db.Date
paid_date DateTime? @db.Date
issued_by String? @db.VarChar(255)
billing_text String? @db.VarChar(500)
language String? @default("cs") @db.VarChar(5)
notes String? @db.Text
internal_notes String? @db.Text
created_at DateTime? @default(now()) @db.DateTime(0)
modified_at DateTime? @db.DateTime(0)
invoice_items invoice_items[]
orders orders? @relation(fields: [order_id], references: [id], onUpdate: NoAction, map: "invoices_ibfk_1")
customers customers? @relation(fields: [customer_id], references: [id], onUpdate: NoAction, map: "invoices_ibfk_2")
@@index([customer_id], map: "customer_id")
@@index([due_date], map: "idx_invoices_due_date")
@@index([status, issue_date], map: "idx_invoices_status_issue")
@@index([status, due_date], map: "idx_invoices_status_due")
@@index([order_id], map: "order_id")
}
model item_templates {
id Int @id @default(autoincrement())
name String? @db.VarChar(255)
description String? @db.Text
default_price Decimal? @default(0.00) @db.Decimal(12, 2)
category String? @db.VarChar(100)
uuid String? @db.VarChar(36)
modified_at DateTime? @db.DateTime(0)
is_deleted Boolean? @default(false)
sync_version Int? @default(0)
}
model leave_balances {
id Int @id @default(autoincrement())
user_id Int
year Int
vacation_total Decimal? @default(160.00) @db.Decimal(5, 2)
vacation_used Decimal? @default(0.00) @db.Decimal(5, 2)
sick_used Decimal? @default(0.00) @db.Decimal(5, 2)
created_at DateTime? @default(now()) @db.Timestamp(0)
updated_at DateTime? @default(now()) @db.Timestamp(0)
users users @relation(fields: [user_id], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "leave_balances_ibfk_1")
@@unique([user_id, year], map: "idx_leave_balances_user_year")
}
model leave_requests {
id Int @id @default(autoincrement())
user_id Int
leave_type leave_requests_leave_type
date_from DateTime @db.Date
date_to DateTime @db.Date
total_hours Decimal @db.Decimal(5, 2)
total_days Int
notes String? @db.Text
status leave_requests_status? @default(pending)
reviewer_id Int?
reviewer_note String? @db.Text
reviewed_at DateTime? @db.DateTime(0)
created_at DateTime? @default(now()) @db.Timestamp(0)
updated_at DateTime? @default(now()) @db.Timestamp(0)
users_leave_requests_user_idTousers users @relation("leave_requests_user_idTousers", fields: [user_id], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "leave_requests_ibfk_1")
users_leave_requests_reviewer_idTousers users? @relation("leave_requests_reviewer_idTousers", fields: [reviewer_id], references: [id], onUpdate: NoAction, map: "leave_requests_ibfk_2")
@@index([user_id, status], map: "idx_leave_requests_user_status")
@@index([status], map: "idx_status")
@@index([reviewer_id], map: "reviewer_id")
}
model number_sequences {
id Int @id @default(autoincrement())
type String? @db.VarChar(50)
year Int?
last_number Int? @default(0)
@@unique([type, year], map: "idx_number_sequences_type_year")
}
model order_items {
id Int @id @default(autoincrement())
order_id Int
description String? @db.VarChar(500)
item_description String? @db.Text
quantity Decimal? @default(1.000) @db.Decimal(12, 3)
unit String? @db.VarChar(20)
unit_price Decimal? @default(0.00) @db.Decimal(12, 2)
is_included_in_total Boolean? @default(true)
position Int? @default(0)
modified_at DateTime? @db.DateTime(0)
orders orders @relation(fields: [order_id], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "order_items_ibfk_1")
@@index([order_id], map: "order_id")
}
model order_sections {
id Int @id @default(autoincrement())
order_id Int
title String? @db.VarChar(500)
title_cz String? @db.VarChar(500)
content String? @db.Text
position Int? @default(0)
modified_at DateTime? @db.DateTime(0)
orders orders @relation(fields: [order_id], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "order_sections_ibfk_1")
@@index([order_id], map: "order_id")
}
model orders {
id Int @id @default(autoincrement())
order_number String? @unique(map: "idx_orders_number_unique") @db.VarChar(50)
customer_order_number String? @db.VarChar(100)
attachment_data Bytes?
attachment_name String? @db.VarChar(255)
quotation_id Int?
customer_id Int?
status String? @default("prijata") @db.VarChar(30)
currency String? @default("CZK") @db.VarChar(10)
language String? @default("cs") @db.VarChar(5)
vat_rate Decimal? @default(21.00) @db.Decimal(5, 2)
apply_vat Boolean? @default(true)
exchange_rate Decimal? @default(1.0000) @db.Decimal(10, 4)
scope_title String? @db.VarChar(500)
scope_description String? @db.Text
notes String? @db.Text
created_at DateTime? @default(now()) @db.DateTime(0)
modified_at DateTime? @db.DateTime(0)
invoices invoices[]
order_items order_items[]
order_sections order_sections[]
quotations quotations? @relation(fields: [quotation_id], references: [id], onUpdate: NoAction, map: "orders_ibfk_1")
customers customers? @relation(fields: [customer_id], references: [id], onUpdate: NoAction, map: "orders_ibfk_2")
projects projects[]
@@index([customer_id], map: "customer_id")
@@index([quotation_id], map: "quotation_id")
}
model permissions {
id Int @id @default(autoincrement())
name String @unique(map: "name") @db.VarChar(50)
display_name String @db.VarChar(100)
description String? @db.Text
module String @db.VarChar(50)
created_at DateTime? @default(now()) @db.Timestamp(0)
role_permissions role_permissions[]
}
model project_notes {
id Int @id @default(autoincrement())
project_id Int
user_id Int?
user_name String? @db.VarChar(100)
content String? @db.Text
created_at DateTime? @default(now()) @db.DateTime(0)
projects projects @relation(fields: [project_id], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "project_notes_ibfk_1")
@@index([project_id], map: "project_id")
}
model projects {
id Int @id @default(autoincrement())
project_number String? @unique @db.VarChar(50)
name String? @db.VarChar(255)
customer_id Int?
responsible_user_id Int?
quotation_id Int?
order_id Int?
status String? @default("aktivni") @db.VarChar(30)
start_date DateTime? @db.Date
end_date DateTime? @db.Date
notes String? @db.Text
created_at DateTime? @default(now()) @db.DateTime(0)
modified_at DateTime? @db.DateTime(0)
attendance_project_logs attendance_project_logs[]
project_notes project_notes[]
users users? @relation(fields: [responsible_user_id], references: [id], onUpdate: NoAction, map: "fk_projects_responsible_user")
customers customers? @relation(fields: [customer_id], references: [id], onUpdate: NoAction, map: "projects_ibfk_1")
quotations quotations? @relation(fields: [quotation_id], references: [id], onUpdate: NoAction, map: "projects_ibfk_2")
orders orders? @relation(fields: [order_id], references: [id], onUpdate: NoAction, map: "projects_ibfk_3")
@@index([customer_id], map: "customer_id")
@@index([responsible_user_id], map: "fk_projects_responsible_user")
@@index([order_id], map: "order_id")
@@index([quotation_id], map: "quotation_id")
}
model quotation_items {
id Int @id @default(autoincrement())
quotation_id Int
position Int? @default(0)
description String? @db.VarChar(500)
item_description String? @db.Text
quantity Decimal? @default(1.000) @db.Decimal(12, 3)
unit String? @db.VarChar(20)
unit_price Decimal? @default(0.00) @db.Decimal(12, 2)
is_included_in_total Boolean? @default(true)
uuid String? @db.VarChar(36)
modified_at DateTime? @db.DateTime(0)
is_deleted Boolean? @default(false)
sync_version Int? @default(0)
quotations quotations @relation(fields: [quotation_id], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "quotation_items_ibfk_1")
@@index([quotation_id], map: "quotation_id")
}
model quotations {
id Int @id @default(autoincrement())
quotation_number String? @unique @db.VarChar(50)
project_code String? @db.VarChar(50)
customer_id Int?
created_at DateTime? @default(now()) @db.DateTime(0)
valid_until DateTime? @db.Date
currency String? @default("CZK") @db.VarChar(10)
language String? @default("cs") @db.VarChar(5)
vat_rate Decimal? @default(21.00) @db.Decimal(5, 2)
apply_vat Boolean? @default(true)
exchange_rate Decimal? @default(1.0000) @db.Decimal(10, 4)
exchange_rate_date DateTime? @db.Date
order_id Int?
status String @default("active") @db.VarChar(20)
scope_title String? @db.VarChar(500)
scope_description String? @db.Text
locked_by Int?
locked_at DateTime? @db.DateTime(0)
uuid String? @db.VarChar(36)
modified_at DateTime? @db.DateTime(0)
sync_version Int? @default(0)
orders orders[]
projects projects[]
quotation_items quotation_items[]
customers customers? @relation(fields: [customer_id], references: [id], onUpdate: NoAction, map: "quotations_ibfk_1")
scope_sections scope_sections[]
@@index([customer_id], map: "customer_id")
@@index([quotation_number], map: "idx_quotations_number")
}
model received_invoices {
id Int @id @default(autoincrement()) @db.UnsignedInt
month Int @db.UnsignedTinyInt
year Int @db.UnsignedSmallInt
supplier_name String @db.VarChar(255)
invoice_number String? @db.VarChar(100)
description String? @db.VarChar(500)
amount Decimal @default(0.00) @db.Decimal(12, 2)
currency String @default("CZK") @db.VarChar(3)
vat_rate Decimal @default(21.00) @db.Decimal(5, 2)
vat_amount Decimal @default(0.00) @db.Decimal(12, 2)
issue_date DateTime? @db.Date
due_date DateTime? @db.Date
paid_date DateTime? @db.Date
status received_invoices_status @default(unpaid)
file_name String? @db.VarChar(255)
file_mime String? @db.VarChar(100)
file_size Int? @db.UnsignedInt
notes String? @db.Text
uploaded_by Int?
created_at DateTime @default(now()) @db.DateTime(0)
modified_at DateTime @default(now()) @db.DateTime(0)
@@index([year, month], map: "idx_month_year")
@@index([status], map: "idx_status")
@@index([supplier_name], map: "idx_supplier")
}
/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments
model refresh_tokens {
id Int @id @default(autoincrement()) @db.UnsignedInt
user_id Int
token_hash String @unique(map: "token_hash") @db.VarChar(64)
expires_at DateTime @db.DateTime(0)
replaced_at DateTime? @db.DateTime(0)
replaced_by_hash String? @db.VarChar(64)
remember_me Boolean @default(false)
ip_address String? @db.VarChar(45)
user_agent String? @db.VarChar(255)
created_at DateTime? @default(now()) @db.DateTime(0)
@@index([expires_at], map: "idx_refresh_tokens_expires_at")
@@index([user_id, expires_at], map: "idx_refresh_tokens_user_exp")
@@index([user_id], map: "idx_refresh_tokens_user_id")
}
model role_permissions {
role_id Int
permission_id Int
roles roles @relation(fields: [role_id], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "role_permissions_ibfk_1")
permissions permissions @relation(fields: [permission_id], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "role_permissions_ibfk_2")
@@id([role_id, permission_id])
@@index([permission_id], map: "permission_id")
}
model roles {
id Int @id @default(autoincrement())
name String @unique(map: "name") @db.VarChar(50)
display_name String @db.VarChar(100)
description String? @db.Text
created_at DateTime? @default(now()) @db.Timestamp(0)
updated_at DateTime? @default(now()) @db.Timestamp(0)
role_permissions role_permissions[]
users users[]
}
model scope_sections {
id Int @id @default(autoincrement())
quotation_id Int
position Int? @default(0)
title String? @db.VarChar(500)
title_cz String? @db.VarChar(500)
content String? @db.Text
content_editor_height Int?
uuid String? @db.VarChar(36)
modified_at DateTime? @db.DateTime(0)
is_deleted Boolean? @default(false)
sync_version Int? @default(0)
quotations quotations @relation(fields: [quotation_id], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "scope_sections_ibfk_1")
@@index([quotation_id], map: "quotation_id")
}
model scope_template_sections {
id Int @id @default(autoincrement())
scope_template_id Int
position Int? @default(0)
title String? @db.VarChar(500)
title_cz String? @db.VarChar(500)
content String? @db.Text
uuid String? @db.VarChar(36)
modified_at DateTime? @db.DateTime(0)
is_deleted Boolean? @default(false)
sync_version Int? @default(0)
scope_templates scope_templates @relation(fields: [scope_template_id], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "scope_template_sections_ibfk_1")
@@index([scope_template_id], map: "scope_template_id")
}
model scope_templates {
id Int @id @default(autoincrement())
name String? @db.VarChar(255)
title String? @db.VarChar(500)
description String? @db.Text
uuid String? @db.VarChar(36)
modified_at DateTime? @db.DateTime(0)
is_deleted Boolean? @default(false)
sync_version Int? @default(0)
scope_template_sections scope_template_sections[]
}
model totp_login_tokens {
id Int @id @default(autoincrement())
user_id Int
token_hash String @db.VarChar(64)
expires_at DateTime @db.DateTime(0)
created_at DateTime @default(now()) @db.DateTime(0)
@@index([expires_at], map: "idx_expires")
@@index([token_hash], map: "idx_totp_login_tokens_hash")
@@index([user_id], map: "idx_user_id")
}
/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments
model trips {
id Int @id @default(autoincrement())
vehicle_id Int
user_id Int
trip_date DateTime @db.Date
start_km Int
end_km Int
distance Int?
route_from String @db.VarChar(100)
route_to String @db.VarChar(100)
is_business Boolean @default(true)
notes String? @db.Text
created_at DateTime? @default(now()) @db.Timestamp(0)
updated_at DateTime? @default(now()) @db.Timestamp(0)
users users @relation(fields: [user_id], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "trips_user_fk")
vehicles vehicles @relation(fields: [vehicle_id], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "trips_vehicle_fk")
@@index([trip_date], map: "trip_date")
@@index([user_id], map: "user_id")
@@index([vehicle_id], map: "vehicle_id")
}
model users {
id Int @id @default(autoincrement())
username String @unique(map: "username") @db.VarChar(50)
email String @unique(map: "email") @db.VarChar(255)
password_hash String @db.VarChar(255)
first_name String @db.VarChar(50)
last_name String @db.VarChar(50)
role_id Int?
is_active Boolean? @default(true)
last_login DateTime? @db.Timestamp(0)
failed_login_attempts Int? @default(0)
locked_until DateTime? @db.Timestamp(0)
password_changed_at DateTime? @default(now()) @db.Timestamp(0)
created_at DateTime? @default(now()) @db.Timestamp(0)
updated_at DateTime? @default(now()) @db.Timestamp(0)
totp_secret String? @db.VarChar(255)
totp_enabled Boolean @default(false)
totp_backup_codes String? @db.Text
totp_last_used_counter Int?
attendance attendance[]
leave_balances leave_balances[]
leave_requests_leave_requests_user_idTousers leave_requests[] @relation("leave_requests_user_idTousers")
leave_requests_leave_requests_reviewer_idTousers leave_requests[] @relation("leave_requests_reviewer_idTousers")
projects projects[]
trips trips[]
roles roles? @relation(fields: [role_id], references: [id], onUpdate: NoAction, map: "users_ibfk_1")
@@index([is_active], map: "idx_users_is_active")
@@index([role_id], map: "idx_users_role_id")
}
/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments
model vehicles {
id Int @id @default(autoincrement())
spz String @unique(map: "spz") @db.VarChar(20)
name String @db.VarChar(100)
brand String? @db.VarChar(50)
model String? @db.VarChar(50)
initial_km Int @default(0)
actual_km Int @default(0)
is_active Boolean @default(true)
created_at DateTime? @default(now()) @db.Timestamp(0)
updated_at DateTime? @default(now()) @db.Timestamp(0)
trips trips[]
}
enum leave_requests_leave_type {
vacation
sick
unpaid
}
enum leave_requests_status {
pending
approved
rejected
cancelled
}
model invoice_alert_log {
id Int @id @default(autoincrement())
invoice_type String @db.VarChar(20) // "created" or "received"
invoice_id Int
alert_type String @db.VarChar(20) // "3days" or "due"
sent_at DateTime @default(now()) @db.DateTime(0)
created_at DateTime @default(now()) @db.DateTime(0)
@@unique([invoice_type, invoice_id, alert_type])
}
enum received_invoices_status {
unpaid
paid
}
enum attendance_leave_type {
work
vacation
sick
holiday
unpaid
}