b6167bcb-7363-4695-9481-addd81de4367
This commit is contained in:
1 parent
fdc3b82d10
commit
d226dabba3
136 files changed
+13904
-2
No files matched your search
@@ -0,0 +1,277 @@
|
||||
// AOS — Agency Operating System
|
||||
// One deployment = one agency (single tenant). SQLite for this build.
|
||||
// Money is integer cents, tax rates are basis points. No floats for money.
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "sqlite"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Platform
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
email String @unique
|
||||
name String
|
||||
role String @default("owner") // owner|admin|sales|pm|developer|finance|readonly|client
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
// Module registry — installed/enabled/disabled state of each domain module
|
||||
model Module {
|
||||
id String @id // crm|leads|projects|licenses|sales-docs|finance|support|...
|
||||
version String @default("1.0.0")
|
||||
enabled Boolean @default(true)
|
||||
installed Boolean @default(true)
|
||||
nav String? // JSON: [{label,route,permission}]
|
||||
events String? // JSON: {emits:[],listens:[]}
|
||||
updatedAt DateTime @updatedAt
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model Setting {
|
||||
key String @id
|
||||
value String // typed at app layer (encrypted secrets handled separately)
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model AuditLog {
|
||||
id String @id @default(cuid())
|
||||
actor String? // user id or "system"
|
||||
action String // e.g. "crm.deal:update"
|
||||
entity String
|
||||
entityId String
|
||||
before String? // JSON
|
||||
after String? // JSON
|
||||
hash String? // hash chain
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// CRM (Phase 1)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
model Company {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
legalForm String? // GmbH, UG, e.K., GbR, AG, Einzelunternehmen...
|
||||
vatId String? // USt-IdNr
|
||||
registerCourt String?
|
||||
registerNumber String? // HRB ...
|
||||
website String?
|
||||
email String?
|
||||
phone String?
|
||||
city String?
|
||||
zip String?
|
||||
street String?
|
||||
source String? // lead-finder|import|manual|referral
|
||||
tags String? // comma separated
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
persons Person[]
|
||||
deals Deal[]
|
||||
leads Lead[]
|
||||
licenses License[]
|
||||
invoices Invoice[]
|
||||
projects Project[]
|
||||
}
|
||||
|
||||
model Person {
|
||||
id String @id @default(cuid())
|
||||
companyId String?
|
||||
company Company? @relation(fields: [companyId], references: [id])
|
||||
firstName String
|
||||
lastName String
|
||||
email String?
|
||||
phone String?
|
||||
role String? // Geschäftsführer, Marketing, IT...
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model Deal {
|
||||
id String @id @default(cuid())
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id])
|
||||
title String
|
||||
valueCents Int @default(0)
|
||||
probability Int @default(0) // 0-100
|
||||
stage String @default("lead") // pipeline stage key
|
||||
expectedClose DateTime?
|
||||
lossReason String?
|
||||
ownerId String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Leads Finder (Phase 2)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
model Lead {
|
||||
id String @id @default(cuid())
|
||||
// discovered company info (may become a Company when approved)
|
||||
companyName String
|
||||
website String?
|
||||
city String?
|
||||
branch String?
|
||||
// audit + scoring
|
||||
score Int @default(0) // 0-100 weighted rule score
|
||||
scoreLabel String? // new-site|redesign|seo|aeo|shop|maintenance|accessibility
|
||||
evidence String? // JSON array of {id,check,status,detail}
|
||||
explanation String? // LLM draft "why this lead" — every claim links to an evidence id
|
||||
suggestedAngle String? // proposed outreach angle
|
||||
status String @default("pending") // pending|approved|rejected|snoozed|converted
|
||||
reviewReason String?
|
||||
source String? // serpapi|tavily|apify|firecrawl
|
||||
radiusKm Int?
|
||||
// when converted, link to CRM company + deal
|
||||
companyId String?
|
||||
company Company? @relation(fields: [companyId], references: [id])
|
||||
createdAt DateTime @default(now())
|
||||
reviewedAt DateTime?
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Projects (Phase 3)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
model Project {
|
||||
id String @id @default(cuid())
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id])
|
||||
name String
|
||||
type String // website|shop|app|retainer
|
||||
status String @default("planning") // planning|active|review|done|on-hold|cancelled
|
||||
budgetType String @default("fixed") // fixed|time-materials|retainer
|
||||
budgetHours Int?
|
||||
spentHours Int @default(0)
|
||||
fixedPriceCents Int?
|
||||
startDate DateTime?
|
||||
dueDate DateTime?
|
||||
progress Int @default(0) // 0-100
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
tasks Task[]
|
||||
timeEntries TimeEntry[]
|
||||
}
|
||||
|
||||
model Task {
|
||||
id String @id @default(cuid())
|
||||
projectId String
|
||||
project Project @relation(fields: [projectId], references: [id])
|
||||
title String
|
||||
description String?
|
||||
status String @default("todo") // todo|in-progress|review|done
|
||||
assignee String?
|
||||
estimateMin Int?
|
||||
priority String @default("medium") // low|medium|high
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model TimeEntry {
|
||||
id String @id @default(cuid())
|
||||
projectId String
|
||||
project Project @relation(fields: [projectId], references: [id])
|
||||
userId String?
|
||||
description String
|
||||
minutes Int
|
||||
billable Boolean @default(true)
|
||||
rateCentsPerHour Int?
|
||||
invoiced Boolean @default(false)
|
||||
date DateTime @default(now())
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Licenses (Phase 4)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
model License {
|
||||
id String @id @default(cuid())
|
||||
key String @unique
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id])
|
||||
product String // e.g. aos-cms, wp-plugin-xyz
|
||||
plan String // starter|pro|enterprise
|
||||
status String @default("active") // active|suspended|revoked|expired
|
||||
maxActivations Int @default(1)
|
||||
validUntil DateTime?
|
||||
token String? // Ed25519-signed token (mocked)
|
||||
createdAt DateTime @default(now())
|
||||
activations LicenseActivation[]
|
||||
}
|
||||
|
||||
model LicenseActivation {
|
||||
id String @id @default(cuid())
|
||||
licenseId String
|
||||
license License @relation(fields: [licenseId], references: [id])
|
||||
domain String
|
||||
fingerprint String?
|
||||
environment String @default("production") // production|staging
|
||||
version String?
|
||||
lastCheck DateTime @default(now())
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
// Asset & renewal register (what the agency manages/pays for on behalf of clients)
|
||||
model Asset {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
type String // domain|hosting|ssl|plugin-seat|saas
|
||||
provider String? // Ionos, Strato, Cloudflare...
|
||||
companyId String? // may be internal asset
|
||||
costCentsPerMonth Int?
|
||||
renewalDate DateTime
|
||||
rebill Boolean @default(false)
|
||||
markupPct Int @default(0)
|
||||
status String @default("active") // active|expiring|expired|cancelled
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Finance (Phase 5)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
model Invoice {
|
||||
id String @id @default(cuid())
|
||||
number String @unique // gapless, e.g. RE-2026-0001
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id])
|
||||
status String @default("draft") // draft|sent|paid|overdue|cancelled|storno
|
||||
type String @default("final") // final|partial|recurring|credit
|
||||
issueDate DateTime @default(now())
|
||||
dueDate DateTime
|
||||
paidDate DateTime?
|
||||
netCents Int @default(0)
|
||||
taxBp Int @default(1900) // 19% as basis points
|
||||
grossCents Int @default(0)
|
||||
// E-Rechnung / compliance
|
||||
zugferd Boolean @default(false)
|
||||
xrechnung Boolean @default(false)
|
||||
datevExported Boolean @default(false)
|
||||
projectId String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
lines InvoiceLine[]
|
||||
}
|
||||
|
||||
model InvoiceLine {
|
||||
id String @id @default(cuid())
|
||||
invoiceId String
|
||||
invoice Invoice @relation(fields: [invoiceId], references: [id])
|
||||
description String
|
||||
quantity Int @default(1)
|
||||
unitCents Int
|
||||
totalCents Int
|
||||
}
|
||||
Reference in new issue
Block a user