Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM, PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source files covering clients, berths, interests/pipeline, documents/EOI, expenses/invoices, email, notifications, dashboard, admin, and client portal. CI/CD via Gitea Actions with Docker builds. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
31
src/lib/entity-diff.ts
Normal file
31
src/lib/entity-diff.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { diffFields } from '@/lib/audit';
|
||||
|
||||
const SKIP_FIELDS = new Set(['createdAt', 'updatedAt', 'portId']);
|
||||
|
||||
/**
|
||||
* Wraps `diffFields` with automatic exclusion of metadata fields
|
||||
* (createdAt, updatedAt, portId).
|
||||
*/
|
||||
export function diffEntity<T extends Record<string, unknown>>(
|
||||
oldRecord: T,
|
||||
newRecord: Partial<T>,
|
||||
): { changed: boolean; diff: Record<string, { old: unknown; new: unknown }> } {
|
||||
// Only compare keys present in newRecord
|
||||
const filteredOld: Record<string, unknown> = {};
|
||||
const filteredNew: Record<string, unknown> = {};
|
||||
|
||||
for (const key of Object.keys(newRecord)) {
|
||||
if (SKIP_FIELDS.has(key)) continue;
|
||||
filteredOld[key] = oldRecord[key];
|
||||
filteredNew[key] = newRecord[key];
|
||||
}
|
||||
|
||||
const changes = diffFields(filteredOld, filteredNew);
|
||||
|
||||
const diff: Record<string, { old: unknown; new: unknown }> = {};
|
||||
for (const change of changes) {
|
||||
diff[change.field] = { old: change.oldValue, new: change.newValue };
|
||||
}
|
||||
|
||||
return { changed: changes.length > 0, diff };
|
||||
}
|
||||
Reference in New Issue
Block a user