feature: clinic & lab invitation flow added. minimal ui implemented for organizations tab.

This commit is contained in:
2026-05-05 19:50:07 +03:30
parent 43e39883a4
commit adfb5b436e
22 changed files with 1265 additions and 23 deletions

View File

@@ -0,0 +1,33 @@
-- CreateTable
CREATE TABLE "organization_invitations" (
"id" TEXT NOT NULL,
"inviterOrganizationId" TEXT NOT NULL,
"inviterUserId" TEXT NOT NULL,
"invitedOrganizationId" TEXT,
"invitedOrganizationName" TEXT NOT NULL,
"invitedOwnerEmail" TEXT NOT NULL,
"invitedOrganizationType" TEXT NOT NULL,
"tokenHash" TEXT NOT NULL,
"expiresAt" TIMESTAMP(3) NOT NULL,
"acceptedAt" TIMESTAMP(3),
"revokedAt" TIMESTAMP(3),
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "organization_invitations_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "organization_invitations_tokenHash_key" ON "organization_invitations"("tokenHash");
-- CreateIndex
CREATE INDEX "organization_invitations_inviterOrganizationId_createdAt_idx" ON "organization_invitations"("inviterOrganizationId", "createdAt");
-- CreateIndex
CREATE INDEX "organization_invitations_invitedOwnerEmail_createdAt_idx" ON "organization_invitations"("invitedOwnerEmail", "createdAt");
-- AddForeignKey
ALTER TABLE "organization_invitations" ADD CONSTRAINT "organization_invitations_inviterOrganizationId_fkey" FOREIGN KEY ("inviterOrganizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "organization_invitations" ADD CONSTRAINT "organization_invitations_inviterUserId_fkey" FOREIGN KEY ("inviterUserId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@@ -0,0 +1,7 @@
UPDATE "permissions"
SET "name" = 'TAB_ORGANIZATIONS_READ'
WHERE "name" = 'TAB_LAB_READ';
UPDATE "permissions"
SET "name" = 'TAB_ORGANIZATIONS_EDIT'
WHERE "name" = 'TAB_LAB_EDIT';

View File

@@ -21,6 +21,7 @@ model User {
ownedOrganizations Organization[] @relation("OrganizationOwner")
sessions Session[] // 👈 ADD THIS - opposite relation for Session
sentStaffInvites StaffInvitation[]
sentOrganizationInvitations OrganizationInvitation[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@ -57,6 +58,7 @@ model Organization {
sharedWithMe OrganizationLink[] @relation("OrganizationB")
sharedWithOthers OrganizationLink[] @relation("OrganizationA")
sentOrganizationInvitations OrganizationInvitation[] @relation("OrganizationInvitationInviter")
patients Patient[]
createdAt DateTime @default(now())
@@ -211,6 +213,32 @@ model OrganizationLink {
@@map("organization_links")
}
model OrganizationInvitation {
id String @id @default(uuid())
inviterOrganizationId String
inviterUserId String
invitedOrganizationId String?
invitedOrganizationName String
invitedOwnerEmail String
invitedOrganizationType String
tokenHash String @unique
expiresAt DateTime
acceptedAt DateTime?
revokedAt DateTime?
inviterOrganization Organization @relation("OrganizationInvitationInviter", fields: [inviterOrganizationId], references: [id], onDelete: Cascade)
inviterUser User @relation(fields: [inviterUserId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([inviterOrganizationId, createdAt])
@@index([invitedOwnerEmail, createdAt])
@@map("organization_invitations")
}
model Session {
id String @id @default(uuid())
userId String

View File

@@ -74,8 +74,8 @@ async function main() {
permissions: ['TAB_STAFF_READ', 'TAB_STAFF_EDIT'],
},
{
name: 'Labs / Clinics',
permissions: ['TAB_LAB_READ', 'TAB_LAB_EDIT'],
name: 'Organizations',
permissions: ['TAB_ORGANIZATIONS_READ', 'TAB_ORGANIZATIONS_EDIT'],
},
{
name: 'Patients',