fix: Remove unique constraint from template_type and improve AI response handling

Database Changes:
- Remove UNIQUE constraint from mail_templates.template_type
- Allow multiple templates with same type (e.g., multiple bank templates)

Ollama Service Improvements:
- Add detailed logging for AI responses (first 500 chars)
- Check multiple field name variations (subject/Subject/konu/title, body/Body/html/content)
- Improve error messages with actual field names
- Better JSON parsing with fallback
- Clearer prompt instructions to AI

This fixes:
- 400 Validation Error when creating templates with existing type
- AI response parsing issues with different field names
This commit is contained in:
salvacybersec
2025-11-10 23:40:46 +03:00
parent 1107ce1af1
commit 1b3d6f263f
2 changed files with 22 additions and 7 deletions

View File

@@ -14,8 +14,7 @@ const MailTemplate = sequelize.define('MailTemplate', {
template_type: {
type: DataTypes.STRING(50),
allowNull: false,
unique: true,
comment: 'bank, edevlet, corporate, etc.',
comment: 'bank, edevlet, corporate, etc. (multiple templates can have same type)',
},
subject_template: {
type: DataTypes.STRING(500),

View File

@@ -124,11 +124,15 @@ Senaryo: ${scenario}`;
5. Gerçekçi ve ikna edici olmalı
6. Link için {{tracking_url}} placeholder'ını kullan
Örnek format:
ÇOK ÖNEMLİ: Yanıtın SADECE JSON olmalı, başka hiçbir metin olmamalı!
Kesinlikle bu formatta yanıt ver:
{
"subject": "Mail konusu buraya",
"body": "<html>Mail içeriği buraya</html>"
}`;
"body": "<html><body><h2>Başlık</h2><p>Mail içeriği buraya</p><a href='{{tracking_url}}'>Link</a></body></html>"
}
SADECE JSON döndür, hiç açıklama yazma!`;
try {
logger.info(`Generating template for company: ${company_name}, scenario: ${scenario}`);
@@ -157,6 +161,7 @@ Senaryo: ${scenario}`;
const aiResponse = response.data.message.content;
logger.info('Ollama response received');
logger.info(`Raw AI response: ${aiResponse.substring(0, 500)}...`); // Log first 500 chars
// Parse JSON response
let templateData;
@@ -168,14 +173,25 @@ Senaryo: ${scenario}`;
if (jsonMatch) {
templateData = JSON.parse(jsonMatch[0]);
} else {
logger.error(`JSON parse failed. Raw response: ${aiResponse}`);
throw new Error('AI yanıtı JSON formatında değil');
}
}
if (!templateData.subject || !templateData.body) {
throw new Error('AI yanıtında subject veya body eksik');
logger.info(`Parsed template data keys: ${Object.keys(templateData).join(', ')}`);
// Check for various possible field names
const subject = templateData.subject || templateData.Subject || templateData.konu || templateData.title;
const body = templateData.body || templateData.Body || templateData.html || templateData.content || templateData.icerik;
if (!subject || !body) {
logger.error(`Missing fields. Template data: ${JSON.stringify(templateData, null, 2)}`);
throw new Error(`AI yanıtında subject veya body eksik. Mevcut alanlar: ${Object.keys(templateData).join(', ')}`);
}
templateData.subject = subject;
templateData.body = body;
return {
subject_template: templateData.subject,
body_template: templateData.body,