Add business-scoped invoices billed to users.

Introduce invoices.user_id, business template/invoice APIs, and tenant-domain public URLs so business dashboards can issue invoices without platform-scope template mismatches.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-08-11 15:17:03 +03:30
co-authored by Cursor
parent e59db25814
commit 5734a73c9c
8 changed files with 899 additions and 235 deletions
+39 -35
View File
@@ -8,41 +8,42 @@ datasource db {
}
model User {
id BigInt @id @default(autoincrement())
cellNumber String @unique(map: "users_cell_number_unique") @map("cell_number") @db.VarChar(20)
passwordHash String @map("password_hash") @db.VarChar(255)
email String? @db.VarChar(255)
firstName String? @map("first_name") @db.VarChar(100)
lastName String? @map("last_name") @db.VarChar(100)
isActive Boolean @default(true) @map("is_active")
cellVerifiedAt DateTime? @map("cell_verified_at") @db.Timestamptz(6)
lastLoginAt DateTime? @map("last_login_at") @db.Timestamptz(6)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
profile Json @default("{}")
firstNameEn String? @map("first_name_en") @db.VarChar(100)
lastNameEn String? @map("last_name_en") @db.VarChar(100)
oldId BigInt? @map("old_id")
addresses Address[]
authoredBlogs blogs[] @relation("BlogAuthor")
businessCustomers BusinessCustomer[]
businessUsersInvited BusinessUser[] @relation("BusinessInviter")
businessUsers BusinessUser[] @relation("BusinessMember")
carts Cart[]
commentsApproved Comment[] @relation("CommentApprover")
expertReviewsApproved ExpertReview[] @relation("ExpertReviewApprover")
favorites Favorite[]
invoicesIssued Invoice[] @relation("InvoiceIssuer")
mediaUploaded Media[]
ordersCreated Order[] @relation("OrderCreator")
orders Order[] @relation("OrderCustomer")
authoredPortfolios portfolios[] @relation("PortfolioAuthor")
shoppingCardsCreated ShoppingCard[] @relation("ShoppingCardCreator")
shoppingCards ShoppingCard[] @relation("ShoppingCardCustomer")
transactionsCreated Transaction[] @relation("TransactionCreator")
transactions Transaction[] @relation("TransactionCustomer")
userProducts UserProduct[]
userRoles UserRole[]
id BigInt @id @default(autoincrement())
cellNumber String @unique(map: "users_cell_number_unique") @map("cell_number") @db.VarChar(20)
passwordHash String @map("password_hash") @db.VarChar(255)
email String? @db.VarChar(255)
firstName String? @map("first_name") @db.VarChar(100)
lastName String? @map("last_name") @db.VarChar(100)
isActive Boolean @default(true) @map("is_active")
cellVerifiedAt DateTime? @map("cell_verified_at") @db.Timestamptz(6)
lastLoginAt DateTime? @map("last_login_at") @db.Timestamptz(6)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
profile Json @default("{}")
firstNameEn String? @map("first_name_en") @db.VarChar(100)
lastNameEn String? @map("last_name_en") @db.VarChar(100)
oldId BigInt? @map("old_id")
addresses Address[]
authoredBlogs blogs[] @relation("BlogAuthor")
businessCustomers BusinessCustomer[]
businessUsersInvited BusinessUser[] @relation("BusinessInviter")
businessUsers BusinessUser[] @relation("BusinessMember")
carts Cart[]
commentsApproved Comment[] @relation("CommentApprover")
expertReviewsApproved ExpertReview[] @relation("ExpertReviewApprover")
favorites Favorite[]
invoicesIssued Invoice[] @relation("InvoiceIssuer")
invoicesBilled Invoice[] @relation("InvoiceBilledUser")
mediaUploaded Media[]
ordersCreated Order[] @relation("OrderCreator")
orders Order[] @relation("OrderCustomer")
authoredPortfolios portfolios[] @relation("PortfolioAuthor")
shoppingCardsCreated ShoppingCard[] @relation("ShoppingCardCreator")
shoppingCards ShoppingCard[] @relation("ShoppingCardCustomer")
transactionsCreated Transaction[] @relation("TransactionCreator")
transactions Transaction[] @relation("TransactionCustomer")
userProducts UserProduct[]
userRoles UserRole[]
@@index([cellNumber], map: "idx_users_cell_number")
@@map("users")
@@ -1178,6 +1179,7 @@ model Invoice {
topText String? @map("top_text")
invoiceTemplateId BigInt? @map("invoice_template_id")
publicId String @unique(map: "idx_invoices_public_id") @map("public_id") @db.VarChar(32)
userId BigInt @map("user_id")
accounts InvoiceAccount[]
items InvoiceItem[]
keyPoints InvoiceKeyPoint[]
@@ -1185,10 +1187,12 @@ model Invoice {
invoiceTemplate InvoiceTemplate? @relation(fields: [invoiceTemplateId], references: [id], onUpdate: NoAction)
issuer User? @relation("InvoiceIssuer", fields: [issuedBy], references: [id], onUpdate: NoAction)
issuerBusiness Business? @relation("InvoiceIssuerBusiness", fields: [issuerBusinessId], references: [id], onUpdate: NoAction)
user User @relation("InvoiceBilledUser", fields: [userId], references: [id], onUpdate: NoAction)
@@index([businessId, createdAt(sort: Desc)], map: "idx_invoices_business_created")
@@index([ownerScope, createdAt(sort: Desc)], map: "idx_invoices_owner_scope")
@@index([status], map: "idx_invoices_status")
@@index([userId, createdAt(sort: Desc)], map: "idx_invoices_user_created")
@@map("invoices")
}