4553f63deb
- monorepo (npm workspaces): apps/api (Fastify+Prisma+TS), apps/web (Vite+React+TS), packages/shared (zod schemas) - SSO via auth.queo.ru: jose+JWKS plugin, requireDocPermission(viewer|user|admin) - DEV_BYPASS_AUTH for local development (hard-checked off in production) - M2: organization upsert, clients CRUD with search, services catalog with soft-delete - BigInt -> Number serializer for Prisma money columns - Embedded Postgres + npm run dev:demo for one-command local boot - Docker compose for queoserver: postgres + api + web (nginx as ingress proxying /api -> api:3030) - First migration 0_init committed (prisma migrate diff) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
280 lines
9.2 KiB
SQL
280 lines
9.2 KiB
SQL
-- CreateEnum
|
|
CREATE TYPE "DocType" AS ENUM ('contract', 'invoice', 'act', 'upd');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "DocStatus" AS ENUM ('draft', 'issued', 'sent', 'partially_paid', 'paid', 'cancelled', 'signed');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "VatRate" AS ENUM ('none', '0', '5', '7', '10', '20');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "ClientKind" AS ENUM ('ul', 'ip', 'fl');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "TochkaEnv" AS ENUM ('sandbox', 'prod');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "PaymentKind" AS ENUM ('incoming', 'incoming_sbp', 'incoming_sbp_b2b', 'outgoing');
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "Organization" (
|
|
"id" UUID NOT NULL,
|
|
"name" TEXT NOT NULL,
|
|
"inn" TEXT NOT NULL,
|
|
"kpp" TEXT,
|
|
"ogrn" TEXT,
|
|
"legalAddress" TEXT,
|
|
"bankName" TEXT,
|
|
"bankBik" TEXT,
|
|
"bankAccount" TEXT,
|
|
"signatoryName" TEXT,
|
|
"signatoryPosition" TEXT,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "Organization_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "Client" (
|
|
"id" UUID NOT NULL,
|
|
"organizationId" UUID NOT NULL,
|
|
"kind" "ClientKind" NOT NULL,
|
|
"name" TEXT NOT NULL,
|
|
"inn" TEXT,
|
|
"kpp" TEXT,
|
|
"address" TEXT,
|
|
"email" TEXT,
|
|
"phone" TEXT,
|
|
"contactPerson" TEXT,
|
|
"requisitesJson" JSONB,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "Client_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "ServiceCatalog" (
|
|
"id" UUID NOT NULL,
|
|
"organizationId" UUID NOT NULL,
|
|
"name" TEXT NOT NULL,
|
|
"unit" TEXT NOT NULL,
|
|
"defaultPriceCents" BIGINT NOT NULL DEFAULT 0,
|
|
"defaultVat" "VatRate" NOT NULL DEFAULT 'none',
|
|
"notes" TEXT,
|
|
"archivedAt" TIMESTAMP(3),
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "ServiceCatalog_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "DocumentTemplate" (
|
|
"id" UUID NOT NULL,
|
|
"organizationId" UUID NOT NULL,
|
|
"docType" "DocType" NOT NULL,
|
|
"name" TEXT NOT NULL,
|
|
"body" JSONB NOT NULL,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "DocumentTemplate_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "Document" (
|
|
"id" UUID NOT NULL,
|
|
"organizationId" UUID NOT NULL,
|
|
"docType" "DocType" NOT NULL,
|
|
"number" TEXT NOT NULL,
|
|
"issuedAt" TIMESTAMP(3),
|
|
"status" "DocStatus" NOT NULL DEFAULT 'draft',
|
|
"clientId" UUID,
|
|
"parentDocumentId" UUID,
|
|
"body" JSONB NOT NULL,
|
|
"totalCents" BIGINT NOT NULL DEFAULT 0,
|
|
"vatCents" BIGINT NOT NULL DEFAULT 0,
|
|
"currency" TEXT NOT NULL DEFAULT 'RUB',
|
|
"tochkaDocumentId" TEXT,
|
|
"tochkaEnvironment" "TochkaEnv",
|
|
"pdfPath" TEXT,
|
|
"createdBy" TEXT,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "Document_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "DocumentLine" (
|
|
"id" UUID NOT NULL,
|
|
"documentId" UUID NOT NULL,
|
|
"position" INTEGER NOT NULL,
|
|
"serviceId" UUID,
|
|
"name" TEXT NOT NULL,
|
|
"qtyMilli" BIGINT NOT NULL DEFAULT 1000,
|
|
"unit" TEXT NOT NULL,
|
|
"priceCents" BIGINT NOT NULL,
|
|
"vat" "VatRate" NOT NULL DEFAULT 'none',
|
|
"sumCents" BIGINT NOT NULL,
|
|
|
|
CONSTRAINT "DocumentLine_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "Payment" (
|
|
"id" UUID NOT NULL,
|
|
"organizationId" UUID NOT NULL,
|
|
"documentId" UUID,
|
|
"tochkaPaymentId" TEXT NOT NULL,
|
|
"kind" "PaymentKind" NOT NULL,
|
|
"amountCents" BIGINT NOT NULL,
|
|
"payerInn" TEXT,
|
|
"payerName" TEXT,
|
|
"purpose" TEXT,
|
|
"paidAt" TIMESTAMP(3),
|
|
"raw" JSONB NOT NULL,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
CONSTRAINT "Payment_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "TochkaCredential" (
|
|
"id" UUID NOT NULL,
|
|
"organizationId" UUID NOT NULL,
|
|
"environment" "TochkaEnv" NOT NULL,
|
|
"jwtEncrypted" TEXT NOT NULL,
|
|
"customerCode" TEXT NOT NULL,
|
|
"accountCode" TEXT,
|
|
"expiresAt" TIMESTAMP(3),
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "TochkaCredential_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "WebhookEvent" (
|
|
"id" UUID NOT NULL,
|
|
"receivedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"source" TEXT NOT NULL,
|
|
"eventType" TEXT NOT NULL,
|
|
"raw" JSONB NOT NULL,
|
|
"processedAt" TIMESTAMP(3),
|
|
"error" TEXT,
|
|
"dedupeKey" TEXT NOT NULL,
|
|
|
|
CONSTRAINT "WebhookEvent_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "AuditLog" (
|
|
"id" UUID NOT NULL,
|
|
"organizationId" UUID NOT NULL,
|
|
"actorSub" TEXT,
|
|
"action" TEXT NOT NULL,
|
|
"entity" TEXT NOT NULL,
|
|
"entityId" TEXT NOT NULL,
|
|
"diff" JSONB,
|
|
"at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
CONSTRAINT "AuditLog_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "Client_organizationId_idx" ON "Client"("organizationId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "Client_organizationId_name_idx" ON "Client"("organizationId", "name");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "ServiceCatalog_organizationId_idx" ON "ServiceCatalog"("organizationId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "ServiceCatalog_organizationId_archivedAt_idx" ON "ServiceCatalog"("organizationId", "archivedAt");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "DocumentTemplate_organizationId_docType_idx" ON "DocumentTemplate"("organizationId", "docType");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "Document_organizationId_clientId_issuedAt_idx" ON "Document"("organizationId", "clientId", "issuedAt" DESC);
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "Document_organizationId_status_idx" ON "Document"("organizationId", "status");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "Document_tochkaDocumentId_idx" ON "Document"("tochkaDocumentId");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "Document_organizationId_docType_number_key" ON "Document"("organizationId", "docType", "number");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "DocumentLine_documentId_idx" ON "DocumentLine"("documentId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "DocumentLine_serviceId_idx" ON "DocumentLine"("serviceId");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "Payment_tochkaPaymentId_key" ON "Payment"("tochkaPaymentId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "Payment_organizationId_paidAt_idx" ON "Payment"("organizationId", "paidAt" DESC);
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "Payment_documentId_idx" ON "Payment"("documentId");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "TochkaCredential_organizationId_environment_key" ON "TochkaCredential"("organizationId", "environment");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "WebhookEvent_dedupeKey_key" ON "WebhookEvent"("dedupeKey");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "WebhookEvent_source_eventType_receivedAt_idx" ON "WebhookEvent"("source", "eventType", "receivedAt");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "AuditLog_organizationId_at_idx" ON "AuditLog"("organizationId", "at" DESC);
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "AuditLog_entity_entityId_idx" ON "AuditLog"("entity", "entityId");
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "Client" ADD CONSTRAINT "Client_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "ServiceCatalog" ADD CONSTRAINT "ServiceCatalog_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "DocumentTemplate" ADD CONSTRAINT "DocumentTemplate_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "Document" ADD CONSTRAINT "Document_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "Document" ADD CONSTRAINT "Document_clientId_fkey" FOREIGN KEY ("clientId") REFERENCES "Client"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "Document" ADD CONSTRAINT "Document_parentDocumentId_fkey" FOREIGN KEY ("parentDocumentId") REFERENCES "Document"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "DocumentLine" ADD CONSTRAINT "DocumentLine_documentId_fkey" FOREIGN KEY ("documentId") REFERENCES "Document"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "DocumentLine" ADD CONSTRAINT "DocumentLine_serviceId_fkey" FOREIGN KEY ("serviceId") REFERENCES "ServiceCatalog"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "Payment" ADD CONSTRAINT "Payment_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "Payment" ADD CONSTRAINT "Payment_documentId_fkey" FOREIGN KEY ("documentId") REFERENCES "Document"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "TochkaCredential" ADD CONSTRAINT "TochkaCredential_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "AuditLog" ADD CONSTRAINT "AuditLog_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
|