initial commit: rocket.new export of broadcastbeat
This commit is contained in:
92
src/app/api/adops/cron/end-campaigns/route.ts
Normal file
92
src/app/api/adops/cron/end-campaigns/route.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { createClient } from '@/lib/supabase/server';
|
||||
|
||||
async function requireAdmin(request: NextRequest) {
|
||||
const supabase = await createClient();
|
||||
const { data: { user } } = await supabase.auth.getUser();
|
||||
if (!user) return null;
|
||||
const { data: profile } = await supabase
|
||||
.from('user_profiles')
|
||||
.select('role')
|
||||
.eq('id', user.id)
|
||||
.single();
|
||||
if (!profile || !['administrator', 'admin'].includes(profile.role)) return null;
|
||||
return user;
|
||||
}
|
||||
|
||||
// POST /api/adops/cron/end-campaigns — daily midnight check
|
||||
export async function POST(request: NextRequest) {
|
||||
const cronSecret = request.headers.get('x-cron-secret');
|
||||
const isValidCron = cronSecret && cronSecret === process.env.CRON_SECRET;
|
||||
|
||||
if (!isValidCron) {
|
||||
const user = await requireAdmin(request);
|
||||
if (!user) return NextResponse.json({ error: 'Not found' }, { status: 404 });
|
||||
}
|
||||
|
||||
const supabase = await createClient();
|
||||
const today = new Date().toISOString().split('T')[0];
|
||||
|
||||
// Find campaigns that should end today or earlier
|
||||
const { data: expiredCampaigns } = await supabase
|
||||
.from('ad_campaigns')
|
||||
.select('*')
|
||||
.eq('status', 'active')
|
||||
.lte('end_date', today);
|
||||
|
||||
if (!expiredCampaigns?.length) {
|
||||
return NextResponse.json({ success: true, ended: 0 });
|
||||
}
|
||||
|
||||
let ended = 0;
|
||||
for (const campaign of expiredCampaigns) {
|
||||
await supabase
|
||||
.from('ad_campaigns')
|
||||
.update({
|
||||
status: 'ended',
|
||||
deactivated_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString(),
|
||||
})
|
||||
.eq('id', campaign.id);
|
||||
|
||||
// Send end notification
|
||||
try {
|
||||
const { sendToJeffAndRyan, sendToRyanOnly } = await import('@/lib/adops/adOpsEmailSender');
|
||||
const { campaignEndedEmailJeff, campaignEndedEmailRyan } = await import('@/lib/adops/emailTemplates');
|
||||
|
||||
const jeffEmail = campaignEndedEmailJeff({
|
||||
clientName: campaign.client_name,
|
||||
publication: campaign.publication_id,
|
||||
endDate: campaign.end_date,
|
||||
impressions: campaign.impressions || 0,
|
||||
clicks: campaign.clicks || 0,
|
||||
ctr: campaign.ctr || 0,
|
||||
campaignId: campaign.id,
|
||||
});
|
||||
|
||||
await sendToJeffAndRyan({ subject: jeffEmail.subject, html: jeffEmail.html });
|
||||
|
||||
if (campaign.agreed_rate) {
|
||||
const ryanEmail = campaignEndedEmailRyan({
|
||||
clientName: campaign.client_name,
|
||||
publication: campaign.publication_id,
|
||||
endDate: campaign.end_date,
|
||||
impressions: campaign.impressions || 0,
|
||||
clicks: campaign.clicks || 0,
|
||||
ctr: campaign.ctr || 0,
|
||||
campaignId: campaign.id,
|
||||
agreedRate: campaign.agreed_rate,
|
||||
invoiceId: campaign.mooninvoice_invoice_id,
|
||||
invoiceStatus: 'sent',
|
||||
});
|
||||
await sendToRyanOnly({ subject: ryanEmail.subject, html: ryanEmail.html });
|
||||
}
|
||||
} catch (err: any) {
|
||||
console.error('[Cron] Email error for campaign', campaign.id, err.message);
|
||||
}
|
||||
|
||||
ended++;
|
||||
}
|
||||
|
||||
return NextResponse.json({ success: true, ended });
|
||||
}
|
||||
Reference in New Issue
Block a user