Deploy rule, CRM enhancements, Company Employee category, bilingual, contacts module completion
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
97
backend/prisma/clean-and-seed.js
Normal file
97
backend/prisma/clean-and-seed.js
Normal file
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* Production database cleanup + re-seed.
|
||||
* Truncates all tables (data only), then runs the seed to restore base data.
|
||||
*
|
||||
* Usage (from backend directory):
|
||||
* node prisma/clean-and-seed.js
|
||||
*
|
||||
* Or: npm run db:clean-and-seed
|
||||
*
|
||||
* Ensure DATABASE_URL is set (e.g. production). Back up the DB before running.
|
||||
*/
|
||||
|
||||
const { PrismaClient } = require('@prisma/client');
|
||||
const { execSync } = require('child_process');
|
||||
const path = require('path');
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
// All tables from schema (Prisma @@map names) – order does not matter with CASCADE
|
||||
const TABLES = [
|
||||
'audit_logs',
|
||||
'approvals',
|
||||
'notifications',
|
||||
'custom_fields',
|
||||
'attachments',
|
||||
'notes',
|
||||
'activities',
|
||||
'campaigns',
|
||||
'project_expenses',
|
||||
'project_members',
|
||||
'tasks',
|
||||
'project_phases',
|
||||
'projects',
|
||||
'asset_maintenances',
|
||||
'assets',
|
||||
'warehouse_transfers',
|
||||
'inventory_movements',
|
||||
'inventory_items',
|
||||
'product_categories',
|
||||
'products',
|
||||
'warehouses',
|
||||
'invoices',
|
||||
'contracts',
|
||||
'cost_sheets',
|
||||
'quotes',
|
||||
'deals',
|
||||
'pipelines',
|
||||
'contact_relationships',
|
||||
'contact_categories',
|
||||
'contacts',
|
||||
'disciplinary_actions',
|
||||
'employee_trainings',
|
||||
'performance_evaluations',
|
||||
'commissions',
|
||||
'allowances',
|
||||
'salaries',
|
||||
'leaves',
|
||||
'attendances',
|
||||
'position_permissions',
|
||||
'positions',
|
||||
'departments',
|
||||
'employees',
|
||||
'users',
|
||||
];
|
||||
|
||||
async function clean() {
|
||||
console.log('🧹 Truncating all tables...');
|
||||
const quoted = TABLES.map((t) => `"${t}"`).join(', ');
|
||||
await prisma.$executeRawUnsafe(
|
||||
`TRUNCATE TABLE ${quoted} RESTART IDENTITY CASCADE;`
|
||||
);
|
||||
console.log('✅ All tables truncated.');
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const env = process.env.NODE_ENV || 'development';
|
||||
if (process.env.DATABASE_URL?.includes('prod') || env === 'production') {
|
||||
console.log('⚠️ DATABASE_URL appears to be PRODUCTION. Ensure you have a backup.\n');
|
||||
}
|
||||
|
||||
await clean();
|
||||
await prisma.$disconnect();
|
||||
|
||||
console.log('\n🌱 Running seed...\n');
|
||||
const backendDir = path.resolve(__dirname, '..');
|
||||
execSync('node prisma/seed-prod.js', {
|
||||
stdio: 'inherit',
|
||||
cwd: backendDir,
|
||||
env: process.env,
|
||||
});
|
||||
console.log('\n✅ Clean and seed completed.');
|
||||
}
|
||||
|
||||
main().catch((e) => {
|
||||
console.error('❌ Error:', e);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
-- CreateIndex
|
||||
CREATE INDEX "contacts_source_idx" ON "contacts"("source");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "contacts_createdAt_idx" ON "contacts"("createdAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "contacts_parentId_idx" ON "contacts"("parentId");
|
||||
@@ -0,0 +1,8 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "contacts" ADD COLUMN "employeeId" TEXT;
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "contacts_employeeId_key" ON "contacts"("employeeId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "contacts" ADD CONSTRAINT "contacts_employeeId_fkey" FOREIGN KEY ("employeeId") REFERENCES "employees"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
@@ -134,6 +134,7 @@ model Employee {
|
||||
|
||||
// Relations
|
||||
user User?
|
||||
contact Contact?
|
||||
attendances Attendance[]
|
||||
leaves Leave[]
|
||||
salaries Salary[]
|
||||
@@ -401,6 +402,10 @@ model Contact {
|
||||
categories ContactCategory[]
|
||||
tags String[]
|
||||
|
||||
// HR Link - for Company Employee category
|
||||
employeeId String? @unique
|
||||
employee Employee? @relation(fields: [employeeId], references: [id])
|
||||
|
||||
// Hierarchy - for companies/entities
|
||||
parentId String?
|
||||
parent Contact? @relation("ContactHierarchy", fields: [parentId], references: [id])
|
||||
@@ -442,6 +447,9 @@ model Contact {
|
||||
@@index([mobile])
|
||||
@@index([taxNumber])
|
||||
@@index([commercialRegister])
|
||||
@@index([source])
|
||||
@@index([createdAt])
|
||||
@@index([parentId])
|
||||
@@map("contacts")
|
||||
}
|
||||
|
||||
|
||||
@@ -251,6 +251,7 @@ async function main() {
|
||||
{ name: 'Supplier', nameAr: 'مورد', description: 'Product/Service suppliers' },
|
||||
{ name: 'Partner', nameAr: 'شريك', description: 'Business partners' },
|
||||
{ name: 'Lead', nameAr: 'عميل محتمل', description: 'Potential customers' },
|
||||
{ name: 'Company Employee', nameAr: 'موظف الشركة', description: 'Internal company staff' },
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user