FEAT: Aprimora Templates Whatsapp
All checks were successful
Deploy Dev / deploy (push) Successful in 3s
All checks were successful
Deploy Dev / deploy (push) Successful in 3s
This commit is contained in:
parent
3ae6b7e978
commit
22e4742384
@ -65,12 +65,27 @@ export class WhatsappController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Post('templates')
|
@Post('templates')
|
||||||
async saveTemplate(@Body() body: { name: string; content: string }) {
|
async saveTemplate(@Body() body: { name: string; content: string; areaId?: number | null; requestedByRole?: string }) {
|
||||||
return this.whatsappService.saveTemplate(body.name, body.content);
|
return this.whatsappService.saveTemplate(body.name, body.content, body.areaId, body.requestedByRole);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('templates/update/:id')
|
@Post('templates/update/:id')
|
||||||
async updateTemplate(@Param('id') id: string, @Body() body: { name: string; content: string }) {
|
async updateTemplate(@Param('id') id: string, @Body() body: { name: string; content: string; areaId?: number | null }) {
|
||||||
return this.whatsappService.updateTemplate(Number(id), body.name, body.content);
|
return this.whatsappService.updateTemplate(Number(id), body.name, body.content, body.areaId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('templates/approve-admin/:id')
|
||||||
|
async approveTemplateByAdmin(@Param('id') id: string) {
|
||||||
|
return this.whatsappService.approveTemplateByAdmin(Number(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('templates/reject-admin/:id')
|
||||||
|
async rejectTemplateByAdmin(@Param('id') id: string) {
|
||||||
|
return this.whatsappService.rejectTemplateByAdmin(Number(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Delete('templates/:id')
|
||||||
|
async deleteTemplate(@Param('id') id: string) {
|
||||||
|
return this.whatsappService.deleteTemplate(Number(id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,10 +30,25 @@ export class WhatsappService implements OnModuleInit {
|
|||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
name VARCHAR(255) NOT NULL UNIQUE,
|
name VARCHAR(255) NOT NULL UNIQUE,
|
||||||
content TEXT NOT NULL,
|
content TEXT NOT NULL,
|
||||||
|
area_id INTEGER REFERENCES areas (id) ON DELETE SET NULL,
|
||||||
|
status VARCHAR(40) NOT NULL DEFAULT 'approved',
|
||||||
|
requested_by_role VARCHAR(40),
|
||||||
|
admin_approved_at TIMESTAMP WITH TIME ZONE,
|
||||||
|
meta_submitted_at TIMESTAMP WITH TIME ZONE,
|
||||||
|
meta_approved_at TIMESTAMP WITH TIME ZONE,
|
||||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||||
);
|
);
|
||||||
`);
|
`);
|
||||||
|
await this.db.query(`
|
||||||
|
ALTER TABLE whatsapp_templates
|
||||||
|
ADD COLUMN IF NOT EXISTS area_id INTEGER REFERENCES areas (id) ON DELETE SET NULL,
|
||||||
|
ADD COLUMN IF NOT EXISTS status VARCHAR(40) NOT NULL DEFAULT 'approved',
|
||||||
|
ADD COLUMN IF NOT EXISTS requested_by_role VARCHAR(40),
|
||||||
|
ADD COLUMN IF NOT EXISTS admin_approved_at TIMESTAMP WITH TIME ZONE,
|
||||||
|
ADD COLUMN IF NOT EXISTS meta_submitted_at TIMESTAMP WITH TIME ZONE,
|
||||||
|
ADD COLUMN IF NOT EXISTS meta_approved_at TIMESTAMP WITH TIME ZONE;
|
||||||
|
`);
|
||||||
await this.db.query(`
|
await this.db.query(`
|
||||||
INSERT INTO whatsapp_templates (name, content) VALUES
|
INSERT INTO whatsapp_templates (name, content) VALUES
|
||||||
('aviso_fatura', 'Olá, {nome}. Estamos entrando em contato para lembrá-lo que a sua fatura está programada para {data}.'),
|
('aviso_fatura', 'Olá, {nome}. Estamos entrando em contato para lembrá-lo que a sua fatura está programada para {data}.'),
|
||||||
@ -576,28 +591,128 @@ export class WhatsappService implements OnModuleInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getTemplates() {
|
async getTemplates() {
|
||||||
const res = await this.db.query('SELECT * FROM whatsapp_templates ORDER BY id ASC');
|
await this.refreshFakeMetaApprovals();
|
||||||
|
const res = await this.db.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
|
||||||
|
`);
|
||||||
return res.rows;
|
return res.rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getTemplateById(id: number) {
|
private async getTemplateById(id: number) {
|
||||||
|
await this.refreshFakeMetaApprovals();
|
||||||
const res = await this.db.query('SELECT * FROM whatsapp_templates WHERE id = $1 LIMIT 1', [id]);
|
const res = await this.db.query('SELECT * FROM whatsapp_templates WHERE id = $1 LIMIT 1', [id]);
|
||||||
return res.rows[0] || null;
|
return res.rows[0] || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveTemplate(name: string, content: string) {
|
async saveTemplate(name: string, content: string, areaId?: number | null, requestedByRole = 'admin') {
|
||||||
|
const isSupervisor = requestedByRole === 'supervisor';
|
||||||
|
const status = isSupervisor ? 'admin_review' : 'meta_review';
|
||||||
|
const adminApprovedAt = isSupervisor ? null : 'CURRENT_TIMESTAMP';
|
||||||
|
const metaSubmittedAt = isSupervisor ? null : 'CURRENT_TIMESTAMP';
|
||||||
const res = await this.db.query(
|
const res = await this.db.query(
|
||||||
'INSERT INTO whatsapp_templates (name, content) VALUES ($1, $2) ON CONFLICT (name) DO UPDATE SET content = EXCLUDED.content, updated_at = CURRENT_TIMESTAMP RETURNING *',
|
`
|
||||||
[name, content]
|
INSERT INTO whatsapp_templates (
|
||||||
|
name,
|
||||||
|
content,
|
||||||
|
area_id,
|
||||||
|
status,
|
||||||
|
requested_by_role,
|
||||||
|
admin_approved_at,
|
||||||
|
meta_submitted_at,
|
||||||
|
meta_approved_at,
|
||||||
|
updated_at
|
||||||
|
)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, ${adminApprovedAt}, ${metaSubmittedAt}, NULL, CURRENT_TIMESTAMP)
|
||||||
|
ON CONFLICT (name) DO UPDATE SET
|
||||||
|
content = EXCLUDED.content,
|
||||||
|
area_id = EXCLUDED.area_id,
|
||||||
|
status = EXCLUDED.status,
|
||||||
|
requested_by_role = EXCLUDED.requested_by_role,
|
||||||
|
admin_approved_at = EXCLUDED.admin_approved_at,
|
||||||
|
meta_submitted_at = EXCLUDED.meta_submitted_at,
|
||||||
|
meta_approved_at = NULL,
|
||||||
|
updated_at = CURRENT_TIMESTAMP
|
||||||
|
RETURNING *
|
||||||
|
`,
|
||||||
|
[name, content, areaId || null, status, requestedByRole]
|
||||||
);
|
);
|
||||||
return res.rows[0];
|
return res.rows[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateTemplate(id: number, name: string, content: string) {
|
async updateTemplate(id: number, name: string, content: string, areaId?: number | null) {
|
||||||
const res = await this.db.query(
|
const res = await this.db.query(
|
||||||
'UPDATE whatsapp_templates SET name = $1, content = $2, updated_at = CURRENT_TIMESTAMP WHERE id = $3 RETURNING *',
|
`
|
||||||
[name, content, id]
|
UPDATE whatsapp_templates
|
||||||
|
SET
|
||||||
|
name = $1,
|
||||||
|
content = $2,
|
||||||
|
area_id = $3,
|
||||||
|
status = 'meta_review',
|
||||||
|
admin_approved_at = CURRENT_TIMESTAMP,
|
||||||
|
meta_submitted_at = CURRENT_TIMESTAMP,
|
||||||
|
meta_approved_at = NULL,
|
||||||
|
updated_at = CURRENT_TIMESTAMP
|
||||||
|
WHERE id = $4
|
||||||
|
RETURNING *
|
||||||
|
`,
|
||||||
|
[name, content, areaId || null, id]
|
||||||
);
|
);
|
||||||
return res.rows[0];
|
return res.rows[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async approveTemplateByAdmin(id: number) {
|
||||||
|
const res = await this.db.query(
|
||||||
|
`
|
||||||
|
UPDATE whatsapp_templates
|
||||||
|
SET
|
||||||
|
status = 'meta_review',
|
||||||
|
admin_approved_at = CURRENT_TIMESTAMP,
|
||||||
|
meta_submitted_at = CURRENT_TIMESTAMP,
|
||||||
|
meta_approved_at = NULL,
|
||||||
|
updated_at = CURRENT_TIMESTAMP
|
||||||
|
WHERE id = $1
|
||||||
|
RETURNING *
|
||||||
|
`,
|
||||||
|
[id],
|
||||||
|
);
|
||||||
|
return res.rows[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
async rejectTemplateByAdmin(id: number) {
|
||||||
|
const res = await this.db.query(
|
||||||
|
`
|
||||||
|
UPDATE whatsapp_templates
|
||||||
|
SET
|
||||||
|
status = 'rejected',
|
||||||
|
updated_at = CURRENT_TIMESTAMP
|
||||||
|
WHERE id = $1
|
||||||
|
RETURNING *
|
||||||
|
`,
|
||||||
|
[id],
|
||||||
|
);
|
||||||
|
return res.rows[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteTemplate(id: number) {
|
||||||
|
await this.db.query('DELETE FROM whatsapp_templates WHERE id = $1', [id]);
|
||||||
|
return { success: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
private async refreshFakeMetaApprovals() {
|
||||||
|
await this.db.query(`
|
||||||
|
UPDATE whatsapp_templates
|
||||||
|
SET
|
||||||
|
status = 'approved',
|
||||||
|
meta_approved_at = COALESCE(meta_approved_at, meta_submitted_at + INTERVAL '15 minutes'),
|
||||||
|
updated_at = CURRENT_TIMESTAMP
|
||||||
|
WHERE status = 'meta_review'
|
||||||
|
AND meta_submitted_at IS NOT NULL
|
||||||
|
AND meta_submitted_at <= CURRENT_TIMESTAMP - INTERVAL '15 minutes'
|
||||||
|
`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user