- NAS storage for created invoices (PDF via puppeteer), received invoices, and offers with auto-save on create/edit - Deterministic file paths derived from DB fields (no file_path column needed) - Separate NAS mount points: NAS_FINANCIALS_PATH, NAS_OFFERS_PATH - Invoice language field (cs/en) stored per invoice, replaces lang modal - Invoices list filtered by month/year matching KPI card selection - Centralized date helpers (src/utils/date.ts) replacing all .toISOString() calls that returned UTC instead of local time - Attendance project switching uses exact time (not rounded) - Comment cleanup: removed ~100 unnecessary/Czech comments - Removed as-any casts in orders and attendance - Prisma migrations: add invoice language, drop received_invoices BLOB columns Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
76 lines
1.8 KiB
TypeScript
76 lines
1.8 KiB
TypeScript
/**
|
|
* Migrate received invoice files from DB BLOB to NAS storage.
|
|
*
|
|
* Usage: NAS_FINANCIALS_PATH=/mnt/nas/financials npx tsx scripts/migrate-received-invoices-to-nas.ts
|
|
*/
|
|
|
|
import "../src/config/env";
|
|
import { PrismaClient } from "@prisma/client";
|
|
import { nasFinancialsManager } from "../src/services/nas-financials-manager";
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
async function main() {
|
|
if (!nasFinancialsManager.isConfigured()) {
|
|
console.error(
|
|
"NAS_FINANCIALS_PATH is not configured or path does not exist.",
|
|
);
|
|
process.exit(1);
|
|
}
|
|
|
|
const records = await prisma.received_invoices.findMany({
|
|
where: { file_data: { not: null }, file_path: null },
|
|
select: {
|
|
id: true,
|
|
file_data: true,
|
|
file_name: true,
|
|
month: true,
|
|
year: true,
|
|
},
|
|
});
|
|
|
|
console.log(`Found ${records.length} invoices to migrate.`);
|
|
|
|
let migrated = 0;
|
|
let failed = 0;
|
|
|
|
for (const rec of records) {
|
|
if (!rec.file_data) continue;
|
|
|
|
const fileName = rec.file_name || `invoice-${rec.id}.pdf`;
|
|
const result = nasFinancialsManager.saveReceivedInvoice(
|
|
fileName,
|
|
rec.year,
|
|
rec.month,
|
|
Buffer.from(rec.file_data),
|
|
);
|
|
|
|
if ("error" in result) {
|
|
console.error(` FAIL id=${rec.id}: ${result.error}`);
|
|
failed++;
|
|
continue;
|
|
}
|
|
|
|
await prisma.received_invoices.update({
|
|
where: { id: rec.id },
|
|
data: { file_path: result.filePath, file_data: null },
|
|
});
|
|
|
|
migrated++;
|
|
if (migrated % 50 === 0) {
|
|
console.log(` Progress: ${migrated}/${records.length}...`);
|
|
}
|
|
}
|
|
|
|
console.log(
|
|
`Done. Migrated: ${migrated}, Failed: ${failed}, Total: ${records.length}`,
|
|
);
|
|
}
|
|
|
|
main()
|
|
.catch((e) => {
|
|
console.error(e);
|
|
process.exit(1);
|
|
})
|
|
.finally(() => prisma.$disconnect());
|