CentralBackend/repositories/template/DocumentTemplateRepository.js

181 lines
7.4 KiB
JavaScript

const db = require('../../database/database');
const { logger } = require('../../middleware/logger');
class DocumentTemplateRepository {
async create(data, conn) {
logger.info('DocumentTemplateRepository.create:start', { name: data.name, type: data.type });
// ADDED: validate required fields + normalize optional fields
const required = ['name', 'type', 'storageKey', 'lang'];
for (const k of required) {
const v = data[k];
if (v === undefined || v === null || String(v).trim() === '') {
const err = new Error(`Invalid document template: missing field "${k}"`);
err.code = 'INVALID_TEMPLATE_DATA';
logger.error('DocumentTemplateRepository.create:invalid', { field: k });
throw err;
}
}
const name = String(data.name);
const type = String(data.type);
const storageKey = String(data.storageKey);
const description = data.description === undefined ? null : data.description; // avoid undefined bind
const lang = String(data.lang);
const allowedUserTypes = new Set(['personal', 'company', 'both']);
const user_type = allowedUserTypes.has(data.user_type || data.userType) ? (data.user_type || data.userType) : 'both';
const query = `
INSERT INTO document_templates (name, type, storageKey, description, lang, user_type, version, state, createdAt, updatedAt)
VALUES (?, ?, ?, ?, ?, ?, 1, 'inactive', NOW(), NOW())
`;
try {
if (conn) {
const [res] = await conn.execute(query, [name, type, storageKey, description, lang, user_type]);
const insertId = res && (res.insertId || res[0]?.insertId);
logger.info('DocumentTemplateRepository.create:success', { id: insertId || res.insertId });
return { id: insertId || res.insertId, name, type, storageKey, description, lang, user_type, version: 1, state: 'inactive' };
}
const result = await db.execute(query, [name, type, storageKey, description, lang, user_type]);
const insertId = result && result.insertId ? result.insertId : (Array.isArray(result) && result[0] && result[0].insertId ? result[0].insertId : undefined);
logger.info('DocumentTemplateRepository.create:success', { id: insertId });
return { id: insertId, name, type, storageKey, description, lang, user_type, version: 1, state: 'inactive' };
} catch (error) {
logger.error('DocumentTemplateRepository.create:error', { error: error.message });
throw error;
}
}
async findAll(conn) {
logger.info('DocumentTemplateRepository.findAll:start');
const query = `SELECT * FROM document_templates ORDER BY createdAt DESC`;
try {
if (conn) {
const [rows] = await conn.execute(query);
logger.info('DocumentTemplateRepository.findAll:success');
return rows;
}
const result = await db.execute(query);
// db.execute may return rows directly or [rows, fields]
if (Array.isArray(result) && Array.isArray(result[0])) return result[0];
logger.info('DocumentTemplateRepository.findAll:success');
return result;
} catch (error) {
logger.error('DocumentTemplateRepository.findAll:error', { error: error.message });
throw error;
}
}
async findById(id, conn) {
logger.info('DocumentTemplateRepository.findById:start', { id });
const query = `SELECT * FROM document_templates WHERE id = ? LIMIT 1`;
try {
if (conn) {
const [rows] = await conn.execute(query, [id]);
logger.info('DocumentTemplateRepository.findById:success', { id });
return (rows && rows[0]) ? rows[0] : null;
}
const result = await db.execute(query, [id]);
if (Array.isArray(result) && Array.isArray(result[0])) {
return result[0][0] || null;
}
logger.info('DocumentTemplateRepository.findById:success', { id });
return (result && result[0]) ? result[0] : null;
} catch (error) {
logger.error('DocumentTemplateRepository.findById:error', { id, error: error.message });
throw error;
}
}
async update(id, data, conn) {
logger.info('DocumentTemplateRepository.update:start', { id, data });
// data: { name, type, storageKey, description, lang, version }
const fields = [];
const values = [];
for (const key of ['name', 'type', 'storageKey', 'description', 'lang', 'version', 'user_type']) {
if (data[key] !== undefined) {
fields.push(`${key} = ?`);
values.push(data[key]);
}
}
// Support camelCase input
if (data.userType !== undefined && data.user_type === undefined) {
fields.push(`user_type = ?`);
values.push(data.userType);
}
// Do not update state here
if (!fields.length) return false;
const query = `
UPDATE document_templates SET ${fields.join(', ')}, updatedAt = NOW()
WHERE id = ?
`;
values.push(id);
try {
if (conn) await conn.execute(query, values);
else await db.execute(query, values);
logger.info('DocumentTemplateRepository.update:success', { id });
return true;
} catch (error) {
logger.error('DocumentTemplateRepository.update:error', { id, error: error.message });
throw error;
}
}
async updateState(id, state, conn) {
logger.info('DocumentTemplateRepository.updateState:start', { id, state });
const query = `
UPDATE document_templates SET state = ?, updatedAt = NOW()
WHERE id = ?
`;
try {
if (conn) await conn.execute(query, [state, id]);
else await db.execute(query, [state, id]);
logger.info('DocumentTemplateRepository.updateState:success', { id, state });
return true;
} catch (error) {
logger.error('DocumentTemplateRepository.updateState:error', { id, error: error.message });
throw error;
}
}
async delete(id, conn) {
logger.info('DocumentTemplateRepository.delete:start', { id });
const query = `DELETE FROM document_templates WHERE id = ?`;
try {
if (conn) await conn.execute(query, [id]);
else await db.execute(query, [id]);
logger.info('DocumentTemplateRepository.delete:success', { id });
return true;
} catch (error) {
logger.error('DocumentTemplateRepository.delete:error', { id, error: error.message });
throw error;
}
}
async findActiveByUserType(userType, templateType = null, conn) {
logger.info('DocumentTemplateRepository.findActiveByUserType:start', { userType, templateType });
const safeType = (userType === 'personal' || userType === 'company') ? userType : 'personal';
let query = `SELECT * FROM document_templates WHERE state = 'active' AND (user_type = ? OR user_type = 'both')`;
const params = [safeType];
if (templateType) {
query += ` AND type = ?`;
params.push(templateType);
}
query += ` ORDER BY createdAt DESC`;
try {
if (conn) {
const [rows] = await conn.execute(query, params);
logger.info('DocumentTemplateRepository.findActiveByUserType:success', { count: rows.length });
return rows;
}
const result = await db.execute(query, params);
const rows = Array.isArray(result) && Array.isArray(result[0]) ? result[0] : result;
logger.info('DocumentTemplateRepository.findActiveByUserType:success', { count: rows.length });
return rows;
} catch (error) {
logger.error('DocumentTemplateRepository.findActiveByUserType:error', { error: error.message });
throw error;
}
}
}
module.exports = new DocumentTemplateRepository();