Fixing Excel login error

This commit is contained in:
2026-10-03 11:32:37 +03:30
parent 5d5b3a3213
commit 5784b09232
28 changed files with 716 additions and 249 deletions
+41 -17
View File
@@ -2,23 +2,37 @@ import { BadRequestException } from '@nestjs/common';
import ExcelJS from 'exceljs';
export function cellStr(value: ExcelJS.CellValue | undefined): string {
if (value == null) return '';
if (typeof value === 'string' || typeof value === 'number') {
return String(value).trim();
try {
if (value == null) return '';
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
return String(value).trim();
}
if (value instanceof Date) {
return Number.isNaN(value.getTime()) ? '' : value.toISOString();
}
if (typeof value === 'object' && 'richText' in value && Array.isArray(value.richText)) {
return value.richText.map((part) => part?.text ?? '').join('').trim();
}
if (typeof value === 'object' && 'text' in value && typeof value.text === 'string') {
return value.text.trim();
}
if (typeof value === 'object' && 'result' in value && value.result != null) {
const result = value.result;
if (typeof result === 'string' || typeof result === 'number' || typeof result === 'boolean') {
return String(result).trim();
}
if (result instanceof Date) {
return Number.isNaN(result.getTime()) ? '' : result.toISOString();
}
return '';
}
if (typeof value === 'object' && 'error' in value && value.error != null) {
return String(value.error).trim();
}
return '';
} catch {
return '';
}
if (typeof value === 'object' && 'richText' in value && Array.isArray(value.richText)) {
return value.richText.map((part) => part.text).join('').trim();
}
if (typeof value === 'object' && 'text' in value && typeof value.text === 'string') {
return value.text.trim();
}
if (typeof value === 'object' && 'result' in value && value.result != null) {
return String(value.result).trim();
}
if (value instanceof Date) {
return value.toISOString();
}
return String(value).trim();
}
export function normalizeHeader(raw: string) {
@@ -182,7 +196,17 @@ export async function workbookFromUpload(file: Express.Multer.File | undefined)
throw new BadRequestException('فایل اکسل انتخاب نشده است');
}
const wb = new ExcelJS.Workbook();
await wb.xlsx.load(Uint8Array.from(file.buffer) as unknown as ExcelJS.Buffer);
try {
// Pass Node Buffer directly — Uint8Array copies can break ExcelJS on some runtimes.
await wb.xlsx.load(file.buffer as unknown as ExcelJS.Buffer);
} catch (err) {
const detail = err instanceof Error ? err.message : '';
throw new BadRequestException(
detail.includes('central directory') || detail.includes('zip')
? 'فایل اکسل نامعتبر است. فقط فرمت .xlsx پشتیبانی می‌شود (نه .xls یا csv).'
: 'خواندن فایل اکسل ناموفق بود. فایل را با فرمت .xlsx ذخیره کنید و دوباره تلاش کنید.',
);
}
const sheet = wb.worksheets[0];
if (!sheet) throw new BadRequestException('شیت اکسل پیدا نشد');
return sheet;
+17 -4
View File
@@ -1,4 +1,5 @@
import {
BadRequestException,
Body,
Controller,
Delete,
@@ -14,6 +15,7 @@ import {
UseInterceptors,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { memoryStorage } from 'multer';
import type { Response } from 'express';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
import { CurrentUser } from '../auth/current-user.decorator';
@@ -23,6 +25,11 @@ import { CreateCompanyDto, ListQueryDto, UpdateCompanyDto } from './dto';
import { ContactsExcelService } from './contacts-excel.service';
import { brand } from '@mento/shared';
const excelUpload = FileInterceptor('file', {
storage: memoryStorage(),
limits: { fileSize: 15_000_000 },
});
@Controller('companies')
@UseGuards(JwtAuthGuard)
export class CompaniesController {
@@ -57,18 +64,24 @@ export class CompaniesController {
}
@Post('import/preview')
@UseInterceptors(FileInterceptor('file'))
previewImport(@UploadedFile() file: Express.Multer.File) {
@UseInterceptors(excelUpload)
previewImport(@UploadedFile() file?: Express.Multer.File) {
if (!file?.buffer?.length) {
throw new BadRequestException('فایل ارسال نشده');
}
return this.excelService.previewCompanies(file);
}
@Post('import')
@UseInterceptors(FileInterceptor('file'))
@UseInterceptors(excelUpload)
import(
@CurrentUser() user: Actor,
@UploadedFile() file: Express.Multer.File,
@UploadedFile() file?: Express.Multer.File,
@Body('mapping') mapping?: string,
) {
if (!file?.buffer?.length) {
throw new BadRequestException('فایل ارسال نشده');
}
return this.excelService.importCompanies(user, file, mapping);
}
+17 -6
View File
@@ -1,4 +1,5 @@
import {
BadRequestException,
Body,
Controller,
Delete,
@@ -14,6 +15,7 @@ import {
UseInterceptors,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { memoryStorage } from 'multer';
import type { Response } from 'express';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
import { CurrentUser } from '../auth/current-user.decorator';
@@ -25,6 +27,11 @@ import { PeopleService } from './people.service';
import { ContactsExcelService } from './contacts-excel.service';
import { brand } from '@mento/shared';
const excelUpload = FileInterceptor('file', {
storage: memoryStorage(),
limits: { fileSize: 15_000_000 },
});
@Controller('people')
@UseGuards(JwtAuthGuard, OrgModuleGuard)
@RequireOrgModule('customers')
@@ -61,20 +68,24 @@ export class PeopleController {
}
@Post('import/preview')
@UseInterceptors(FileInterceptor('file'))
previewImport(
@UploadedFile() file: Express.Multer.File,
) {
@UseInterceptors(excelUpload)
previewImport(@UploadedFile() file?: Express.Multer.File) {
if (!file?.buffer?.length) {
throw new BadRequestException('فایل ارسال نشده');
}
return this.excelService.previewPeople(file);
}
@Post('import')
@UseInterceptors(FileInterceptor('file'))
@UseInterceptors(excelUpload)
import(
@CurrentUser() user: Actor,
@UploadedFile() file: Express.Multer.File,
@UploadedFile() file?: Express.Multer.File,
@Body('mapping') mapping?: string,
) {
if (!file?.buffer?.length) {
throw new BadRequestException('فایل ارسال نشده');
}
return this.excelService.importPeople(user, file, mapping);
}