Add Documents tab and include document metadata in financial export
Validate / validate (push) Successful in 26s
Validate / validate (push) Successful in 26s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -21,7 +21,9 @@ import {
|
||||
users,
|
||||
companyBankAccounts,
|
||||
companyCards,
|
||||
companyAddresses
|
||||
companyAddresses,
|
||||
companyDocuments,
|
||||
companyDocumentVersions
|
||||
} from '../db/schema.js';
|
||||
import { csvBuild } from '$lib/utils/csv.js';
|
||||
import { CARRIER_LABELS } from '../shipping/index.js';
|
||||
@@ -74,6 +76,7 @@ export async function buildFinancialExport(
|
||||
` company_bank_accounts.csv — company bank accounts`,
|
||||
` company_cards.csv — company credit/debit cards (last 4 only)`,
|
||||
` company_addresses.csv — legal/shipping/billing/other addresses`,
|
||||
` company_documents.csv — uploaded document metadata (files not bundled)`,
|
||||
` projects.csv — all projects (active + inactive)`,
|
||||
` parties.csv — all customers/suppliers (incl. archived; see deletedAt)`,
|
||||
` employees.csv — all employees (incl. terminated/archived)`,
|
||||
@@ -210,6 +213,77 @@ export async function buildFinancialExport(
|
||||
zip.file('company_addresses.csv', withBom(csvBuild(rows)));
|
||||
}
|
||||
|
||||
// ── company_documents.csv ──────────────────────────
|
||||
{
|
||||
const docRows = await db
|
||||
.select()
|
||||
.from(companyDocuments)
|
||||
.where(eq(companyDocuments.companyId, companyId))
|
||||
.orderBy(asc(companyDocuments.category), asc(companyDocuments.title));
|
||||
|
||||
// Latest version per document (joined)
|
||||
const latestByDoc = new Map<
|
||||
string,
|
||||
{
|
||||
versionNumber: number;
|
||||
fileName: string;
|
||||
mimeType: string;
|
||||
sizeBytes: number;
|
||||
uploadedBy: string | null;
|
||||
uploadedAt: Date;
|
||||
}
|
||||
>();
|
||||
if (docRows.length > 0) {
|
||||
const versionRows = await db
|
||||
.select({
|
||||
documentId: companyDocumentVersions.documentId,
|
||||
versionNumber: companyDocumentVersions.versionNumber,
|
||||
fileName: companyDocumentVersions.fileName,
|
||||
mimeType: companyDocumentVersions.mimeType,
|
||||
sizeBytes: companyDocumentVersions.sizeBytes,
|
||||
uploadedBy: companyDocumentVersions.uploadedBy,
|
||||
uploadedAt: companyDocumentVersions.uploadedAt
|
||||
})
|
||||
.from(companyDocumentVersions)
|
||||
.where(
|
||||
inArray(
|
||||
companyDocumentVersions.documentId,
|
||||
docRows.map((d) => d.id)
|
||||
)
|
||||
);
|
||||
for (const v of versionRows) {
|
||||
const existing = latestByDoc.get(v.documentId);
|
||||
if (!existing || v.versionNumber > existing.versionNumber) {
|
||||
latestByDoc.set(v.documentId, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const rows: unknown[][] = [
|
||||
[
|
||||
'id', 'category', 'customLabel', 'title', 'description', 'expiresAt',
|
||||
'currentVersion', 'currentFilename', 'currentSizeBytes', 'currentMimeType',
|
||||
'uploadedBy', 'uploadedAt', 'deletedAt', 'createdAt', 'updatedAt'
|
||||
]
|
||||
];
|
||||
for (const d of docRows) {
|
||||
const latest = latestByDoc.get(d.id);
|
||||
rows.push([
|
||||
d.id, d.category, d.customLabel ?? '', d.title, d.description ?? '',
|
||||
d.expiresAt ?? '',
|
||||
latest?.versionNumber ?? '',
|
||||
latest?.fileName ?? '',
|
||||
latest?.sizeBytes ?? '',
|
||||
latest?.mimeType ?? '',
|
||||
latest?.uploadedBy ?? '',
|
||||
latest?.uploadedAt.toISOString() ?? '',
|
||||
d.deletedAt ? d.deletedAt.toISOString() : '',
|
||||
d.createdAt.toISOString(), d.updatedAt.toISOString()
|
||||
]);
|
||||
}
|
||||
zip.file('company_documents.csv', withBom(csvBuild(rows)));
|
||||
}
|
||||
|
||||
// ── projects.csv ────────────────────────────────────
|
||||
const projectRows = await db
|
||||
.select()
|
||||
|
||||
@@ -33,7 +33,10 @@
|
||||
]
|
||||
: []),
|
||||
...(data.companyRoles.some((r) => r === 'admin' || r === 'manager' || r === 'accountant')
|
||||
? [{ href: `/companies/${data.company.id}/profile`, label: 'Profile' }]
|
||||
? [
|
||||
{ href: `/companies/${data.company.id}/profile`, label: 'Profile' },
|
||||
{ href: `/companies/${data.company.id}/documents`, label: 'Documents' }
|
||||
]
|
||||
: []),
|
||||
...(data.companyRoles.includes('admin') || data.companyRoles.includes('accountant')
|
||||
? [{ href: `/companies/${data.company.id}/export`, label: 'Export' }]
|
||||
|
||||
Reference in New Issue
Block a user