Reworks the T&C feature per review:
- categories are user-defined DATA, not a fixed enum — admins add new ones;
- ALL PO T&Cs are catalogued, incl. the previously-fixed boilerplate (seeded
under a "General" category) and an "Others" bucket;
- the PO form is a dynamic editor: "+ Add term", pick a category, type/pick a
clause.
- schema: TermsCategory (name/sortOrder/isActive) + TermsCondition (categoryId
FK + text + isDefault + isActive). PurchaseOrder.terms Json snapshot. Migration
seeds every standard line as a clause (named slots, the two fixed lines under
General, empty Others); isDefault rows pre-fill new POs.
- admin /admin/terms: Add/Edit clause form's category is a combobox — typing a
new name creates the category; isDefault checkbox.
- PO editor components/po/po-terms-editor.tsx: dynamic rows (category + clause
comboboxes), used by new/edit/manager-edit forms; new POs pre-fill from
getDefaultPoTerms, edits load po.terms or legacyPoTerms (old tc* + fixed lines).
- storage: PurchaseOrder.terms ([{category,text}]) supersedes tc* for export +
detail; null on old POs falls back to tc* + fixed lines. parsePoTerms validates.
- export route + po-detail render from terms when present.
- tests rewritten for category creation + catalogue/default helpers.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
52 lines
3.1 KiB
SQL
52 lines
3.1 KiB
SQL
-- CreateTable: user-defined T&C categories
|
|
CREATE TABLE "TermsCategory" (
|
|
"id" TEXT NOT NULL,
|
|
"name" TEXT NOT NULL,
|
|
"sortOrder" INTEGER NOT NULL DEFAULT 0,
|
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "TermsCategory_pkey" PRIMARY KEY ("id")
|
|
);
|
|
CREATE UNIQUE INDEX "TermsCategory_name_key" ON "TermsCategory"("name");
|
|
|
|
-- CreateTable: clauses belonging to a category
|
|
CREATE TABLE "TermsCondition" (
|
|
"id" TEXT NOT NULL,
|
|
"categoryId" TEXT NOT NULL,
|
|
"text" TEXT NOT NULL,
|
|
"isDefault" BOOLEAN NOT NULL DEFAULT false,
|
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
|
"sortOrder" INTEGER NOT NULL DEFAULT 0,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "TermsCondition_pkey" PRIMARY KEY ("id")
|
|
);
|
|
CREATE INDEX "TermsCondition_categoryId_idx" ON "TermsCondition"("categoryId");
|
|
ALTER TABLE "TermsCondition" ADD CONSTRAINT "TermsCondition_categoryId_fkey" FOREIGN KEY ("categoryId") REFERENCES "TermsCategory"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
-- Dynamic T&C snapshot on the PO
|
|
ALTER TABLE "PurchaseOrder" ADD COLUMN "terms" JSONB;
|
|
|
|
-- Seed: every standard PO T&C line becomes a catalogued clause. "General" holds
|
|
-- the previously-fixed boilerplate; the five named slots keep their default
|
|
-- wording; "Others" is an empty bucket admins fill. isDefault rows pre-fill new POs.
|
|
INSERT INTO "TermsCategory" ("id", "name", "sortOrder", "updatedAt") VALUES
|
|
('tcat_general', 'General', 0, CURRENT_TIMESTAMP),
|
|
('tcat_delivery', 'Delivery', 1, CURRENT_TIMESTAMP),
|
|
('tcat_dispatch', 'Dispatch Instructions',2, CURRENT_TIMESTAMP),
|
|
('tcat_inspect', 'Inspection', 3, CURRENT_TIMESTAMP),
|
|
('tcat_transit', 'Transit Insurance', 4, CURRENT_TIMESTAMP),
|
|
('tcat_payment', 'Payment Terms', 5, CURRENT_TIMESTAMP),
|
|
('tcat_others', 'Others', 6, CURRENT_TIMESTAMP);
|
|
|
|
INSERT INTO "TermsCondition" ("id", "categoryId", "text", "isDefault", "sortOrder", "updatedAt") VALUES
|
|
('tcc_fixed1', 'tcat_general', 'Please quote this purchase order no. for further communications and invoices pertaining to this indent.', true, 0, CURRENT_TIMESTAMP),
|
|
('tcc_fixed2', 'tcat_general', 'We encourage bulk packaging and avoid plastic. No asbestos to be used in any product or packing material.', true, 1, CURRENT_TIMESTAMP),
|
|
('tcc_delivery', 'tcat_delivery', 'Within 4 to 5 days', true, 0, CURRENT_TIMESTAMP),
|
|
('tcc_dispatch', 'tcat_dispatch', 'To be transported to site address as above. Freight Supplier''s A/C', true, 0, CURRENT_TIMESTAMP),
|
|
('tcc_inspect', 'tcat_inspect', 'NA', true, 0, CURRENT_TIMESTAMP),
|
|
('tcc_transit', 'tcat_transit', 'NA', true, 0, CURRENT_TIMESTAMP),
|
|
('tcc_payment', 'tcat_payment', 'Within 30 days from delivery.', true, 0, CURRENT_TIMESTAMP);
|