omnichannel-backend/src/modules/whatsapp/repositories/whatsapp-template.repository.ts
Rafael Lopes 7617480242 FIX: importFromMeta resolve conflito de nome com templates locais existentes
ON CONFLICT (name) DO UPDATE atualiza meta info em templates locais com mesmo nome mas sem meta_template_name. Remove catch silencioso e loga falhas de importacao.
2026-07-23 17:28:14 -03:00

224 lines
7.4 KiB
TypeScript

import { Injectable } from '@nestjs/common';
import { DatabaseService } from '../../../infra/database/database.service';
@Injectable()
export class WhatsappTemplateRepository {
constructor(private readonly database: DatabaseService) {}
listTemplates() {
return this.database.query(`
SELECT
wt.*,
a.nome AS area_nome
FROM whatsapp_templates wt
LEFT JOIN areas a ON a.id = wt.area_id
ORDER BY wt.id ASC
`);
}
getTemplateById(id: number) {
return this.database.query('SELECT * FROM whatsapp_templates WHERE id = $1 LIMIT 1', [id]);
}
saveTemplate(input: {
name: string;
content: string;
category: string;
areaId?: number | null;
language: string;
metaTemplateName: string;
headerType?: string | null;
headerText?: string | null;
footerText?: string | null;
buttonsJson: string | null;
bodyVariablesJson: string | null;
}) {
return this.database.query(
`
INSERT INTO whatsapp_templates (
name, content, category, area_id, language,
meta_template_name, header_type, header_text, footer_text,
buttons, body_variables, status, updated_at
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10::jsonb, $11::jsonb, 'draft', CURRENT_TIMESTAMP)
ON CONFLICT (name) DO UPDATE SET
content = EXCLUDED.content,
category = EXCLUDED.category,
area_id = EXCLUDED.area_id,
language = EXCLUDED.language,
meta_template_name = EXCLUDED.meta_template_name,
header_type = EXCLUDED.header_type,
header_text = EXCLUDED.header_text,
footer_text = EXCLUDED.footer_text,
buttons = EXCLUDED.buttons,
body_variables = EXCLUDED.body_variables,
status = 'draft',
meta_status = NULL,
meta_template_id = NULL,
meta_submitted_at = NULL,
meta_approved_at = NULL,
updated_at = CURRENT_TIMESTAMP
RETURNING *
`,
[
input.name,
input.content,
input.category,
input.areaId || null,
input.language,
input.metaTemplateName,
input.headerType || null,
input.headerText || null,
input.footerText || null,
input.buttonsJson,
input.bodyVariablesJson,
],
);
}
updateTemplate(
id: number,
input: {
name: string;
content: string;
category: string;
areaId?: number | null;
language: string;
metaTemplateName: string;
headerType?: string | null;
headerText?: string | null;
footerText?: string | null;
buttonsJson: string | null;
bodyVariablesJson: string | null;
},
) {
return this.database.query(
`
UPDATE whatsapp_templates SET
name = $1,
content = $2,
category = $3,
area_id = $4,
language = $5,
meta_template_name = $6,
header_type = $7,
header_text = $8,
footer_text = $9,
buttons = $10::jsonb,
body_variables = $11::jsonb,
status = 'draft',
meta_status = NULL,
meta_template_id = NULL,
meta_submitted_at = NULL,
meta_approved_at = NULL,
updated_at = CURRENT_TIMESTAMP
WHERE id = $12
RETURNING *
`,
[
input.name,
input.content,
input.category,
input.areaId || null,
input.language,
input.metaTemplateName,
input.headerType || null,
input.headerText || null,
input.footerText || null,
input.buttonsJson,
input.bodyVariablesJson,
id,
],
);
}
updateMetaInfo(
id: number,
info: { metaTemplateId?: string; metaTemplateName?: string; metaStatus: string },
) {
return this.database.query(
`UPDATE whatsapp_templates SET
meta_template_id = COALESCE($2, meta_template_id),
meta_template_name = COALESCE($3, meta_template_name),
meta_status = $4,
meta_submitted_at = CURRENT_TIMESTAMP,
status = 'pending',
updated_at = CURRENT_TIMESTAMP
WHERE id = $1
RETURNING *`,
[id, info.metaTemplateId || null, info.metaTemplateName || null, info.metaStatus],
);
}
async updateMetaStatusByName(metaName: string, metaStatus: string, metaId: string): Promise<number> {
const result = await this.database.query(
`UPDATE whatsapp_templates SET
meta_status = $2,
meta_template_id = COALESCE($3, meta_template_id),
meta_approved_at = CASE WHEN $2 = 'APPROVED' THEN CURRENT_TIMESTAMP ELSE meta_approved_at END,
updated_at = CURRENT_TIMESTAMP
WHERE meta_template_name = $1`,
[metaName, metaStatus, metaId || null],
);
return result.rowCount || 0;
}
async importFromMeta(input: {
metaTemplateId: string;
metaTemplateName: string;
metaStatus: string;
language: string;
category: string;
content: string;
headerType?: string | null;
headerText?: string | null;
footerText?: string | null;
buttonsJson: string | null;
}): Promise<boolean> {
try {
const result = await this.database.query(
`INSERT INTO whatsapp_templates (
name, content, category, language,
meta_template_name, meta_template_id, meta_status,
header_type, header_text, footer_text, buttons, body_variables,
status, meta_approved_at, updated_at
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11::jsonb, NULL,
CASE WHEN $7 = 'APPROVED' THEN 'approved' ELSE 'pending' END,
CASE WHEN $7 = 'APPROVED' THEN CURRENT_TIMESTAMP ELSE NULL END,
CURRENT_TIMESTAMP
)
ON CONFLICT (name) DO UPDATE SET
meta_template_name = EXCLUDED.meta_template_name,
meta_template_id = EXCLUDED.meta_template_id,
meta_status = EXCLUDED.meta_status,
content = CASE WHEN whatsapp_templates.meta_template_name IS NULL THEN EXCLUDED.content ELSE whatsapp_templates.content END,
status = CASE WHEN EXCLUDED.meta_status = 'APPROVED' THEN 'approved' ELSE whatsapp_templates.status END,
meta_approved_at = CASE WHEN EXCLUDED.meta_status = 'APPROVED' THEN CURRENT_TIMESTAMP ELSE whatsapp_templates.meta_approved_at END,
updated_at = CURRENT_TIMESTAMP
WHERE whatsapp_templates.meta_template_name IS NULL`,
[
input.metaTemplateName,
input.content,
input.category,
input.language,
input.metaTemplateName,
input.metaTemplateId,
input.metaStatus,
input.headerType || null,
input.headerText || null,
input.footerText || null,
input.buttonsJson,
],
);
return (result.rowCount || 0) > 0;
} catch (err: any) {
throw new Error(`importFromMeta "${input.metaTemplateName}": ${err.message}`);
}
}
deleteTemplate(id: number) {
return this.database.query('DELETE FROM whatsapp_templates WHERE id = $1 RETURNING meta_template_name', [id]);
}
}