202 lines
6.7 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.campaignsService = void 0;
const client_1 = require("@prisma/client");
const database_1 = require("../../../config/database");
const error_handler_1 = require("../../../middleware/error-handler");
const campaignSelect = {
id: true,
slug: true,
title: true,
description: true,
emailSubject: true,
emailBody: true,
callToAction: true,
coverPhoto: true,
status: true,
allowSmtpEmail: true,
allowMailtoLink: true,
collectUserInfo: true,
showEmailCount: true,
showCallCount: true,
allowEmailEditing: true,
allowCustomRecipients: true,
showResponseWall: true,
highlightCampaign: true,
targetGovernmentLevels: true,
createdByUserId: true,
createdByUserEmail: true,
createdByUserName: true,
createdAt: true,
updatedAt: true,
_count: {
select: {
emails: true,
responses: true,
},
},
};
function generateSlug(title) {
return title
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-+|-+$/g, '')
.slice(0, 80);
}
async function resolveSlugCollision(slug, excludeId) {
let candidate = slug;
let suffix = 2;
while (true) {
const existing = await database_1.prisma.campaign.findUnique({
where: { slug: candidate },
select: { id: true },
});
if (!existing || (excludeId && existing.id === excludeId)) {
return candidate;
}
candidate = `${slug}-${suffix}`;
suffix++;
}
}
exports.campaignsService = {
async findAll(filters, user) {
const { page, limit, search, status } = filters;
const skip = (page - 1) * limit;
const where = {};
if (search) {
where.OR = [
{ title: { contains: search, mode: 'insensitive' } },
{ description: { contains: search, mode: 'insensitive' } },
];
}
if (status)
where.status = status;
// Non-admin users only see their own campaigns
const adminRoles = [client_1.UserRole.SUPER_ADMIN, client_1.UserRole.INFLUENCE_ADMIN, client_1.UserRole.MAP_ADMIN];
if (user && !adminRoles.includes(user.role)) {
where.createdByUserId = user.id;
}
const [campaigns, total] = await Promise.all([
database_1.prisma.campaign.findMany({
where,
select: campaignSelect,
skip,
take: limit,
orderBy: { createdAt: 'desc' },
}),
database_1.prisma.campaign.count({ where }),
]);
return {
campaigns,
pagination: {
page,
limit,
total,
totalPages: Math.ceil(total / limit),
},
};
},
async findById(id) {
const campaign = await database_1.prisma.campaign.findUnique({
where: { id },
select: campaignSelect,
});
if (!campaign) {
throw new error_handler_1.AppError(404, 'Campaign not found', 'CAMPAIGN_NOT_FOUND');
}
return campaign;
},
async findBySlug(slug) {
const campaign = await database_1.prisma.campaign.findUnique({
where: { slug },
select: campaignSelect,
});
if (!campaign) {
throw new error_handler_1.AppError(404, 'Campaign not found', 'CAMPAIGN_NOT_FOUND');
}
return campaign;
},
async create(data, user) {
const baseSlug = generateSlug(data.title);
const slug = await resolveSlugCollision(baseSlug);
// Look up user name from DB
const dbUser = await database_1.prisma.user.findUnique({
where: { id: user.id },
select: { name: true },
});
// If highlighting this campaign, unset any other highlighted campaign
if (data.highlightCampaign) {
await database_1.prisma.campaign.updateMany({
where: { highlightCampaign: true },
data: { highlightCampaign: false },
});
}
const campaign = await database_1.prisma.campaign.create({
data: {
...data,
slug,
createdByUserId: user.id,
createdByUserEmail: user.email,
createdByUserName: dbUser?.name ?? null,
},
select: campaignSelect,
});
return campaign;
},
async update(id, data) {
const existing = await database_1.prisma.campaign.findUnique({ where: { id } });
if (!existing) {
throw new error_handler_1.AppError(404, 'Campaign not found', 'CAMPAIGN_NOT_FOUND');
}
const updateData = { ...data };
// Regenerate slug if title changes
if (data.title && data.title !== existing.title) {
const baseSlug = generateSlug(data.title);
updateData.slug = await resolveSlugCollision(baseSlug, id);
}
// If highlighting this campaign, unset any other highlighted campaign
if (data.highlightCampaign) {
await database_1.prisma.campaign.updateMany({
where: { highlightCampaign: true, id: { not: id } },
data: { highlightCampaign: false },
});
}
const campaign = await database_1.prisma.campaign.update({
where: { id },
data: updateData,
select: campaignSelect,
});
return campaign;
},
async findActiveCampaigns() {
return database_1.prisma.campaign.findMany({
where: { status: 'ACTIVE' },
select: campaignSelect,
orderBy: [
{ highlightCampaign: 'desc' },
{ createdAt: 'desc' },
],
});
},
async findBySlugPublic(slug) {
const campaign = await database_1.prisma.campaign.findUnique({
where: { slug },
select: campaignSelect,
});
if (!campaign) {
throw new error_handler_1.AppError(404, 'Campaign not found', 'CAMPAIGN_NOT_FOUND');
}
if (campaign.status !== 'ACTIVE') {
throw new error_handler_1.AppError(404, 'Campaign not found', 'CAMPAIGN_NOT_FOUND');
}
return campaign;
},
async delete(id) {
const existing = await database_1.prisma.campaign.findUnique({ where: { id } });
if (!existing) {
throw new error_handler_1.AppError(404, 'Campaign not found', 'CAMPAIGN_NOT_FOUND');
}
await database_1.prisma.campaign.delete({ where: { id } });
},
};
//# sourceMappingURL=campaigns.service.js.map