Revert "feat: WhatsApp notification helper + phase 4 migration (recheck_round, WhatsApp settings)"
This reverts commit b6845f5bb5.
This commit is contained in:
@@ -3,12 +3,7 @@ export const dynamic = 'force-dynamic'
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { createClient } from '@/lib/supabase/server'
|
||||
|
||||
const ALLOWED_KEYS = [
|
||||
'ANTHROPIC_API_KEY',
|
||||
'VOYAGE_API_KEY',
|
||||
'META_WHATSAPP_PHONE_NUMBER_ID',
|
||||
'META_WHATSAPP_ACCESS_TOKEN',
|
||||
] as const
|
||||
const ALLOWED_KEYS = ['ANTHROPIC_API_KEY', 'VOYAGE_API_KEY'] as const
|
||||
type SettingKey = typeof ALLOWED_KEYS[number]
|
||||
|
||||
async function requireAdmin(supabase: Awaited<ReturnType<typeof createClient>>) {
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
export async function sendWhatsAppMessage(
|
||||
phoneNumber: string,
|
||||
templateName: string,
|
||||
parameters: string[],
|
||||
phoneNumberId: string,
|
||||
accessToken: string,
|
||||
): Promise<void> {
|
||||
const sanitized = phoneNumber.replace(/[^0-9]/g, '')
|
||||
if (!sanitized) return
|
||||
|
||||
const body = {
|
||||
messaging_product: 'whatsapp',
|
||||
to: sanitized,
|
||||
type: 'template',
|
||||
template: {
|
||||
name: templateName,
|
||||
language: { code: 'en_US' },
|
||||
components: [
|
||||
{
|
||||
type: 'body',
|
||||
parameters: parameters.map(text => ({ type: 'text', text })),
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
const res = await fetch(
|
||||
`https://graph.facebook.com/v19.0/${phoneNumberId}/messages`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${accessToken}`,
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
}
|
||||
)
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error(`WhatsApp API error: ${res.status}`)
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
-- Add effectiveness recheck round tracking to capa_actions
|
||||
ALTER TABLE capa_actions
|
||||
ADD COLUMN IF NOT EXISTS effectiveness_recheck_round INT NOT NULL DEFAULT 0;
|
||||
|
||||
-- WhatsApp and effectiveness recheck credentials for Settings UI
|
||||
INSERT INTO app_settings (key, value, updated_at, updated_by)
|
||||
VALUES
|
||||
('META_WHATSAPP_PHONE_NUMBER_ID', '', now(), NULL),
|
||||
('META_WHATSAPP_ACCESS_TOKEN', '', now(), NULL)
|
||||
ON CONFLICT (key) DO NOTHING;
|
||||
@@ -1,58 +0,0 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||
import { sendWhatsAppMessage } from '@/lib/notifications/whatsapp'
|
||||
|
||||
const fetchMock = vi.fn()
|
||||
vi.stubGlobal('fetch', fetchMock)
|
||||
|
||||
describe('sendWhatsAppMessage', () => {
|
||||
beforeEach(() => fetchMock.mockClear())
|
||||
|
||||
it('posts to Meta Graph API with correct template structure', async () => {
|
||||
fetchMock.mockResolvedValueOnce(
|
||||
new Response('{"messages":[{"id":"wamid.abc"}]}', { status: 200 })
|
||||
)
|
||||
await sendWhatsAppMessage(
|
||||
'60123456789',
|
||||
'ims_incident_alert',
|
||||
['SETIA-202407-0001', 'injury', 'Warehouse A'],
|
||||
'test-phone-id',
|
||||
'test-token'
|
||||
)
|
||||
expect(fetchMock).toHaveBeenCalledOnce()
|
||||
const [url, opts] = fetchMock.mock.calls[0]
|
||||
expect(url).toBe('https://graph.facebook.com/v19.0/test-phone-id/messages')
|
||||
expect(opts.method).toBe('POST')
|
||||
expect(opts.headers['Authorization']).toBe('Bearer test-token')
|
||||
const body = JSON.parse(opts.body)
|
||||
expect(body.messaging_product).toBe('whatsapp')
|
||||
expect(body.to).toBe('60123456789')
|
||||
expect(body.type).toBe('template')
|
||||
expect(body.template.name).toBe('ims_incident_alert')
|
||||
expect(body.template.language.code).toBe('en_US')
|
||||
expect(body.template.components[0].parameters).toHaveLength(3)
|
||||
expect(body.template.components[0].parameters[0]).toEqual({ type: 'text', text: 'SETIA-202407-0001' })
|
||||
})
|
||||
|
||||
it('throws on non-2xx response', async () => {
|
||||
fetchMock.mockResolvedValueOnce(
|
||||
new Response('{"error":{"message":"Invalid token"}}', { status: 400 })
|
||||
)
|
||||
await expect(
|
||||
sendWhatsAppMessage('60123456789', 'ims_incident_alert', ['a'], 'pid', 'tok')
|
||||
).rejects.toThrow('WhatsApp API error: 400')
|
||||
})
|
||||
|
||||
it('returns immediately without calling fetch when phoneNumber is empty', async () => {
|
||||
await sendWhatsAppMessage('', 'ims_incident_alert', ['a'], 'pid', 'tok')
|
||||
expect(fetchMock).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('sanitizes phone number — strips spaces, dashes, and plus sign', async () => {
|
||||
fetchMock.mockResolvedValueOnce(
|
||||
new Response('{"messages":[{"id":"x"}]}', { status: 200 })
|
||||
)
|
||||
await sendWhatsAppMessage('+60 12-345 6789', 'ims_incident_alert', ['a'], 'pid', 'tok')
|
||||
const body = JSON.parse(fetchMock.mock.calls[0][1].body)
|
||||
expect(body.to).toBe('60123456789')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user