fix: generate CSV filename from company name instead of using multer callback
Some checks failed
CI/CD Pipeline / Backend - Build, Test & Push (push) Failing after 1m32s
CI/CD Pipeline / Frontend - Build, Test & Push (push) Successful in 11m35s
CI/CD Pipeline / Integration Tests (push) Has been skipped
CI/CD Pipeline / Deployment Summary (push) Has been skipped
CI/CD Pipeline / Discord Notification (Failure) (push) Has been skipped
CI/CD Pipeline / Discord Notification (Success) (push) Has been skipped
Some checks failed
CI/CD Pipeline / Backend - Build, Test & Push (push) Failing after 1m32s
CI/CD Pipeline / Frontend - Build, Test & Push (push) Successful in 11m35s
CI/CD Pipeline / Integration Tests (push) Has been skipped
CI/CD Pipeline / Deployment Summary (push) Has been skipped
CI/CD Pipeline / Discord Notification (Failure) (push) Has been skipped
CI/CD Pipeline / Discord Notification (Success) (push) Has been skipped
Fixed CSV file upload to properly generate filename based on company name. The previous implementation tried to read `req.body.companyName` in multer's filename callback, but the body is not yet parsed at that point, causing files to be named "unknown.csv". ## Solution 1. Use temporary filename during upload (timestamp + random) 2. After validation and parsing, rename file to proper company name format 3. Delete old file if it exists before renaming 4. Store final filename in database configuration ## Changes - Multer filename callback now generates temporary filename - Added file renaming logic after successful validation - Updated database records to use final filename instead of temp name - Added logging for file operations ## Impact - New CSV uploads will have correct filenames (e.g., "ssc-consolidation.csv") - No more "unknown.csv" files - Existing "unknown.csv" needs to be manually deleted via dashboard 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
aeb3d2a75d
commit
f5eabf4861
@ -70,14 +70,12 @@ export class CsvRatesAdminController {
|
||||
storage: diskStorage({
|
||||
destination: './apps/backend/src/infrastructure/storage/csv-storage/rates',
|
||||
filename: (req, file, cb) => {
|
||||
// Generate filename: company-name.csv
|
||||
const companyName = req.body.companyName || 'unknown';
|
||||
const sanitized = companyName
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, '-')
|
||||
.replace(/[^a-z0-9-]/g, '');
|
||||
const filename = `${sanitized}.csv`;
|
||||
cb(null, filename);
|
||||
// Use timestamp + random string to avoid conflicts
|
||||
// We'll rename it later once we have the company name from req.body
|
||||
const timestamp = Date.now();
|
||||
const randomStr = Math.random().toString(36).substring(7);
|
||||
const tempFilename = `temp-${timestamp}-${randomStr}.csv`;
|
||||
cb(null, tempFilename);
|
||||
},
|
||||
}),
|
||||
fileFilter: (req, file, cb) => {
|
||||
@ -147,9 +145,16 @@ export class CsvRatesAdminController {
|
||||
}
|
||||
|
||||
try {
|
||||
// Generate final filename based on company name
|
||||
const sanitizedCompanyName = dto.companyName
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, '-')
|
||||
.replace(/[^a-z0-9-]/g, '');
|
||||
const finalFilename = `${sanitizedCompanyName}.csv`;
|
||||
|
||||
// Auto-convert CSV if needed (FOB FRET → Standard format)
|
||||
const conversionResult = await this.csvConverter.autoConvert(file.path, dto.companyName);
|
||||
const filePathToValidate = conversionResult.convertedPath;
|
||||
let filePathToValidate = conversionResult.convertedPath;
|
||||
|
||||
if (conversionResult.wasConverted) {
|
||||
this.logger.log(
|
||||
@ -177,13 +182,28 @@ export class CsvRatesAdminController {
|
||||
|
||||
this.logger.log(`Successfully parsed ${ratesCount} rates from ${file.filename}`);
|
||||
|
||||
// Rename file to final name (company-name.csv)
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const finalPath = path.join(path.dirname(filePathToValidate), finalFilename);
|
||||
|
||||
// Delete old file if exists
|
||||
if (fs.existsSync(finalPath)) {
|
||||
fs.unlinkSync(finalPath);
|
||||
this.logger.log(`Deleted old file: ${finalFilename}`);
|
||||
}
|
||||
|
||||
// Rename temp file to final name
|
||||
fs.renameSync(filePathToValidate, finalPath);
|
||||
this.logger.log(`Renamed ${file.filename} to ${finalFilename}`);
|
||||
|
||||
// Check if config exists for this company
|
||||
const existingConfig = await this.csvConfigRepository.findByCompanyName(dto.companyName);
|
||||
|
||||
if (existingConfig) {
|
||||
// Update existing configuration
|
||||
await this.csvConfigRepository.update(existingConfig.id, {
|
||||
csvFilePath: file.filename,
|
||||
csvFilePath: finalFilename,
|
||||
uploadedAt: new Date(),
|
||||
uploadedBy: user.id,
|
||||
rowCount: ratesCount,
|
||||
@ -204,7 +224,7 @@ export class CsvRatesAdminController {
|
||||
// Create new configuration
|
||||
await this.csvConfigRepository.create({
|
||||
companyName: dto.companyName,
|
||||
csvFilePath: file.filename,
|
||||
csvFilePath: finalFilename,
|
||||
type: 'CSV_ONLY',
|
||||
hasApi: false,
|
||||
apiConnector: null,
|
||||
@ -226,7 +246,7 @@ export class CsvRatesAdminController {
|
||||
return {
|
||||
success: true,
|
||||
ratesCount,
|
||||
csvFilePath: file.filename,
|
||||
csvFilePath: finalFilename,
|
||||
companyName: dto.companyName,
|
||||
uploadedAt: new Date(),
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user