249 lines
7.0 KiB
JavaScript
249 lines
7.0 KiB
JavaScript
const path = require('path');
|
|
const fs = require('fs');
|
|
const prisma = require('../../config/prisma');
|
|
const env = require('../../config/env');
|
|
const ApiError = require('../../utils/ApiError');
|
|
const auditLog = require('../../utils/auditLog');
|
|
const { encrypt, decrypt } = require('../../utils/encryption');
|
|
|
|
const COMPANY_ID = BigInt(1);
|
|
const EMAIL_SETTINGS_ID = BigInt(1);
|
|
|
|
const buildPublicUrl = (filePath) => {
|
|
if (!filePath) return null;
|
|
const normalized = filePath.replace(/\\/g, '/');
|
|
return normalized.startsWith('/') ? normalized : `/${normalized}`;
|
|
};
|
|
|
|
const unlinkIfExists = (relativePath) => {
|
|
if (!relativePath) return;
|
|
const absolute = path.resolve(process.cwd(), relativePath);
|
|
if (fs.existsSync(absolute)) {
|
|
fs.unlinkSync(absolute);
|
|
}
|
|
};
|
|
|
|
const sanitizeCompany = (row) => {
|
|
if (!row) return null;
|
|
return {
|
|
id: row.id,
|
|
org_name: row.org_name,
|
|
gstin: row.gstin,
|
|
mobile: row.mobile,
|
|
email: row.email,
|
|
website: row.website,
|
|
logo_path: row.logo_path,
|
|
logo_url: buildPublicUrl(row.logo_path),
|
|
favicon_path: row.favicon_path,
|
|
favicon_url: buildPublicUrl(row.favicon_path),
|
|
address: row.address,
|
|
city: row.city,
|
|
state: row.state,
|
|
pincode: row.pincode,
|
|
created_at: row.created_at,
|
|
updated_at: row.updated_at,
|
|
};
|
|
};
|
|
|
|
const sanitizeEmailSettings = (row) => {
|
|
if (!row) return null;
|
|
return {
|
|
id: row.id,
|
|
smtp_host: row.smtp_host,
|
|
smtp_port: row.smtp_port,
|
|
smtp_username: row.smtp_username,
|
|
sender_email: row.sender_email,
|
|
sender_name: row.sender_name,
|
|
has_smtp_password: Boolean(row.smtp_password),
|
|
created_at: row.created_at,
|
|
updated_at: row.updated_at,
|
|
};
|
|
};
|
|
|
|
const getOrCreateCompany = async () => {
|
|
return prisma.company.upsert({
|
|
where: { id: COMPANY_ID },
|
|
create: { id: COMPANY_ID, org_name: '' },
|
|
update: {},
|
|
});
|
|
};
|
|
|
|
const getOrCreateEmailSettings = async () => {
|
|
return prisma.email_settings.upsert({
|
|
where: { id: EMAIL_SETTINGS_ID },
|
|
create: { id: EMAIL_SETTINGS_ID, smtp_port: 587 },
|
|
update: {},
|
|
});
|
|
};
|
|
|
|
const getCompany = async () => sanitizeCompany(await getOrCreateCompany());
|
|
|
|
const updateCompany = async (payload, userId, requestId) => {
|
|
const existing = await getOrCreateCompany();
|
|
|
|
const data = {
|
|
...(payload.org_name !== undefined ? { org_name: payload.org_name || null } : {}),
|
|
...(payload.gstin !== undefined ? { gstin: payload.gstin || null } : {}),
|
|
...(payload.mobile !== undefined ? { mobile: payload.mobile || null } : {}),
|
|
...(payload.email !== undefined ? { email: payload.email || null } : {}),
|
|
...(payload.website !== undefined ? { website: payload.website || null } : {}),
|
|
...(payload.address !== undefined ? { address: payload.address || null } : {}),
|
|
...(payload.city !== undefined ? { city: payload.city || null } : {}),
|
|
...(payload.state !== undefined ? { state: payload.state || null } : {}),
|
|
...(payload.pincode !== undefined ? { pincode: payload.pincode || null } : {}),
|
|
updated_by: userId ? BigInt(userId) : null,
|
|
};
|
|
|
|
const updated = await prisma.company.update({
|
|
where: { id: COMPANY_ID },
|
|
data,
|
|
});
|
|
|
|
await auditLog({
|
|
tableName: 'company',
|
|
recordId: COMPANY_ID,
|
|
action: 'UPDATE',
|
|
oldValue: sanitizeCompany(existing),
|
|
newValue: sanitizeCompany(updated),
|
|
userId,
|
|
requestId,
|
|
});
|
|
|
|
return sanitizeCompany(updated);
|
|
};
|
|
|
|
const updateCompanyLogo = async (file, userId, requestId) => {
|
|
if (!file) throw new ApiError(400, 'Logo file is required');
|
|
|
|
const existing = await getOrCreateCompany();
|
|
unlinkIfExists(existing.logo_path);
|
|
|
|
const logoPath = path.join(env.UPLOAD_DIR, file.filename).replace(/\\/g, '/');
|
|
|
|
const updated = await prisma.company.update({
|
|
where: { id: COMPANY_ID },
|
|
data: {
|
|
logo_path: logoPath,
|
|
updated_by: userId ? BigInt(userId) : null,
|
|
},
|
|
});
|
|
|
|
await auditLog({
|
|
tableName: 'company',
|
|
recordId: COMPANY_ID,
|
|
action: 'UPDATE',
|
|
oldValue: { logo_path: existing.logo_path },
|
|
newValue: { logo_path: updated.logo_path },
|
|
userId,
|
|
requestId,
|
|
});
|
|
|
|
return sanitizeCompany(updated);
|
|
};
|
|
|
|
const updateCompanyFavicon = async (file, userId, requestId) => {
|
|
if (!file) throw new ApiError(400, 'Favicon file is required');
|
|
|
|
const existing = await getOrCreateCompany();
|
|
unlinkIfExists(existing.favicon_path);
|
|
|
|
const faviconPath = path.join(env.UPLOAD_DIR, file.filename).replace(/\\/g, '/');
|
|
|
|
const updated = await prisma.company.update({
|
|
where: { id: COMPANY_ID },
|
|
data: {
|
|
favicon_path: faviconPath,
|
|
updated_by: userId ? BigInt(userId) : null,
|
|
},
|
|
});
|
|
|
|
await auditLog({
|
|
tableName: 'company',
|
|
recordId: COMPANY_ID,
|
|
action: 'UPDATE',
|
|
oldValue: { favicon_path: existing.favicon_path },
|
|
newValue: { favicon_path: updated.favicon_path },
|
|
userId,
|
|
requestId,
|
|
});
|
|
|
|
return sanitizeCompany(updated);
|
|
};
|
|
|
|
const getEmailSettings = async () => sanitizeEmailSettings(await getOrCreateEmailSettings());
|
|
|
|
const updateEmailSettings = async (payload, userId, requestId) => {
|
|
const existing = await getOrCreateEmailSettings();
|
|
|
|
const data = {
|
|
...(payload.smtp_host !== undefined ? { smtp_host: payload.smtp_host || null } : {}),
|
|
...(payload.smtp_port !== undefined ? { smtp_port: payload.smtp_port } : {}),
|
|
...(payload.smtp_username !== undefined ? { smtp_username: payload.smtp_username || null } : {}),
|
|
...(payload.sender_email !== undefined ? { sender_email: payload.sender_email || null } : {}),
|
|
...(payload.sender_name !== undefined ? { sender_name: payload.sender_name || null } : {}),
|
|
updated_by: userId ? BigInt(userId) : null,
|
|
};
|
|
|
|
if (payload.smtp_password !== undefined && payload.smtp_password !== '') {
|
|
data.smtp_password = encrypt(payload.smtp_password);
|
|
}
|
|
|
|
const updated = await prisma.email_settings.update({
|
|
where: { id: EMAIL_SETTINGS_ID },
|
|
data,
|
|
});
|
|
|
|
await auditLog({
|
|
tableName: 'email_settings',
|
|
recordId: EMAIL_SETTINGS_ID,
|
|
action: 'UPDATE',
|
|
oldValue: sanitizeEmailSettings(existing),
|
|
newValue: sanitizeEmailSettings(updated),
|
|
userId,
|
|
requestId,
|
|
});
|
|
|
|
return sanitizeEmailSettings(updated);
|
|
};
|
|
|
|
const getCompanyForDocuments = async () => {
|
|
const row = await getOrCreateCompany();
|
|
return {
|
|
name: row.org_name || 'Company',
|
|
address: row.address || '',
|
|
city: row.city || '',
|
|
state: row.state || '',
|
|
pincode: row.pincode || '',
|
|
gstin: row.gstin || '',
|
|
phone: row.mobile || '',
|
|
email: row.email || '',
|
|
website: row.website || '',
|
|
logo_url: buildPublicUrl(row.logo_path),
|
|
favicon_url: buildPublicUrl(row.favicon_path),
|
|
};
|
|
};
|
|
|
|
const getSmtpConfig = async () => {
|
|
const row = await getOrCreateEmailSettings();
|
|
if (!row.smtp_host) return null;
|
|
return {
|
|
host: row.smtp_host,
|
|
port: row.smtp_port,
|
|
username: row.smtp_username,
|
|
password: row.smtp_password ? decrypt(row.smtp_password) : null,
|
|
fromEmail: row.sender_email,
|
|
fromName: row.sender_name,
|
|
};
|
|
};
|
|
|
|
module.exports = {
|
|
getCompany,
|
|
updateCompany,
|
|
updateCompanyLogo,
|
|
updateCompanyFavicon,
|
|
getEmailSettings,
|
|
updateEmailSettings,
|
|
getCompanyForDocuments,
|
|
getSmtpConfig,
|
|
};
|