c2fcdec85d
Schema: - Site (organizationId, name, slug, domain, apiKey, defaultOfferTemplateId) - Order (full customer fields, status enum, totalCents/vatCents, projectId link, rawPayload) - OrderItem (orderId, position, name, serviceId, qty, unit, price, vat, eventDate) - Migration 3_orders + OrderStatus enum API: - /api/sites — CRUD with apiKey shown only on create/regenerate - /api/orders — list/get/convert-to-project (creates project + matches/creates client by INN) - POST /api/incoming/orders — S2S, X-Site-Key header → resolves Site → creates Order - POST /webhooks/tochka/<secret> — receives raw, dedupes, parses paymentId+purpose, matches by document number regex, creates Payment, updates Document status (paid/partially_paid), propagates Order.status=paid when fully covered Web: - /sites page: list + add site (paste-friendly modal with API key + curl example shown once after create/regenerate) - /orders page: filterable list, link to project - /orders/🆔 view with items + "Перевести в проект" button (creates project, upserts client by INN, links project<-order) - Nav: «Заявки» and «Сайты» added Manual demo flow: 1. /sites → add «Голосования» slug=voting → save the apiKey 2. curl POST /api/incoming/orders with X-Site-Key → order appears in /orders 3. Open order → «Перевести в проект» → project created with client+default 4. Create invoice document in project → «Выставить через Точку» 5. Webhook from sandbox/prod → document.status=paid → order.status=paid Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
88 lines
3.5 KiB
SQL
88 lines
3.5 KiB
SQL
-- CreateEnum
|
|
CREATE TYPE "OrderStatus" AS ENUM ('new', 'accepted', 'invoiced', 'paid', 'fulfilled', 'cancelled');
|
|
|
|
-- CreateTable Site
|
|
CREATE TABLE "Site" (
|
|
"id" UUID NOT NULL,
|
|
"organizationId" UUID NOT NULL,
|
|
"name" TEXT NOT NULL,
|
|
"slug" TEXT NOT NULL,
|
|
"domain" TEXT,
|
|
"apiKey" TEXT NOT NULL,
|
|
"defaultOfferTemplateId" UUID,
|
|
"archivedAt" TIMESTAMP(3),
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
CONSTRAINT "Site_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
CREATE UNIQUE INDEX "Site_apiKey_key" ON "Site"("apiKey");
|
|
CREATE UNIQUE INDEX "Site_organizationId_slug_key" ON "Site"("organizationId", "slug");
|
|
CREATE INDEX "Site_organizationId_idx" ON "Site"("organizationId");
|
|
|
|
ALTER TABLE "Site" ADD CONSTRAINT "Site_organizationId_fkey"
|
|
FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "Site" ADD CONSTRAINT "Site_defaultOfferTemplateId_fkey"
|
|
FOREIGN KEY ("defaultOfferTemplateId") REFERENCES "DocumentTemplate"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
|
|
-- CreateTable Order
|
|
CREATE TABLE "Order" (
|
|
"id" UUID NOT NULL,
|
|
"organizationId" UUID NOT NULL,
|
|
"siteId" UUID,
|
|
"projectId" UUID,
|
|
"status" "OrderStatus" NOT NULL DEFAULT 'new',
|
|
"customerName" TEXT NOT NULL,
|
|
"customerInn" TEXT,
|
|
"customerKpp" TEXT,
|
|
"customerEmail" TEXT,
|
|
"customerPhone" TEXT,
|
|
"customerAddress" TEXT,
|
|
"customerKind" "ClientKind" NOT NULL DEFAULT 'ul',
|
|
"totalCents" BIGINT NOT NULL DEFAULT 0,
|
|
"vatCents" BIGINT NOT NULL DEFAULT 0,
|
|
"currency" TEXT NOT NULL DEFAULT 'RUB',
|
|
"acceptedOfferAt" TIMESTAMP(3),
|
|
"notes" TEXT,
|
|
"rawPayload" JSONB,
|
|
"archivedAt" TIMESTAMP(3),
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
CONSTRAINT "Order_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
CREATE INDEX "Order_organizationId_status_idx" ON "Order"("organizationId", "status");
|
|
CREATE INDEX "Order_organizationId_siteId_idx" ON "Order"("organizationId", "siteId");
|
|
CREATE INDEX "Order_projectId_idx" ON "Order"("projectId");
|
|
|
|
ALTER TABLE "Order" ADD CONSTRAINT "Order_organizationId_fkey"
|
|
FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "Order" ADD CONSTRAINT "Order_siteId_fkey"
|
|
FOREIGN KEY ("siteId") REFERENCES "Site"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
ALTER TABLE "Order" ADD CONSTRAINT "Order_projectId_fkey"
|
|
FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
|
|
-- CreateTable OrderItem
|
|
CREATE TABLE "OrderItem" (
|
|
"id" UUID NOT NULL,
|
|
"orderId" UUID NOT NULL,
|
|
"position" INTEGER NOT NULL,
|
|
"name" TEXT NOT NULL,
|
|
"serviceId" UUID,
|
|
"qtyMilli" BIGINT NOT NULL DEFAULT 1000,
|
|
"unit" TEXT NOT NULL DEFAULT 'шт',
|
|
"priceCents" BIGINT NOT NULL,
|
|
"vat" "VatRate" NOT NULL DEFAULT 'none',
|
|
"sumCents" BIGINT NOT NULL,
|
|
"eventDate" TIMESTAMP(3),
|
|
CONSTRAINT "OrderItem_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
CREATE INDEX "OrderItem_orderId_idx" ON "OrderItem"("orderId");
|
|
CREATE INDEX "OrderItem_serviceId_idx" ON "OrderItem"("serviceId");
|
|
|
|
ALTER TABLE "OrderItem" ADD CONSTRAINT "OrderItem_orderId_fkey"
|
|
FOREIGN KEY ("orderId") REFERENCES "Order"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "OrderItem" ADD CONSTRAINT "OrderItem_serviceId_fkey"
|
|
FOREIGN KEY ("serviceId") REFERENCES "ServiceCatalog"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|