Initial BizOne portal setup
This commit is contained in:
42
backend/prisma/seed-admin.js
Normal file
42
backend/prisma/seed-admin.js
Normal file
@ -0,0 +1,42 @@
|
||||
const path = require('node:path');
|
||||
const { PrismaClient } = require('@prisma/client');
|
||||
const bcrypt = require('bcryptjs');
|
||||
const dotenv = require('dotenv');
|
||||
|
||||
dotenv.config({ path: path.resolve(process.cwd(), '../.env'), quiet: true });
|
||||
dotenv.config({ path: path.resolve(process.cwd(), '.env'), quiet: true });
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function main() {
|
||||
const email = 'admin@example.com';
|
||||
const password = 'ChangeMe123!';
|
||||
const passwordHash = await bcrypt.hash(password, 10);
|
||||
|
||||
const user = await prisma.user.upsert({
|
||||
where: { email },
|
||||
update: {
|
||||
name: 'System Admin',
|
||||
passwordHash,
|
||||
status: 'active',
|
||||
},
|
||||
create: {
|
||||
name: 'System Admin',
|
||||
email,
|
||||
passwordHash,
|
||||
status: 'active',
|
||||
},
|
||||
});
|
||||
|
||||
console.log(`Seeded admin user: ${user.email}`);
|
||||
console.log(`Recommended credentials: ${email} / ${password}`);
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
180
backend/prisma/seed-campaigns.js
Normal file
180
backend/prisma/seed-campaigns.js
Normal file
@ -0,0 +1,180 @@
|
||||
const path = require('node:path');
|
||||
const { PrismaClient } = require('@prisma/client');
|
||||
const dotenv = require('dotenv');
|
||||
const { randomUUID } = require('node:crypto');
|
||||
|
||||
dotenv.config({ path: path.resolve(process.cwd(), '../.env'), quiet: true });
|
||||
dotenv.config({ path: path.resolve(process.cwd(), '.env'), quiet: true });
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
const sentAt = new Date('2024-07-15T09:45:00.000Z');
|
||||
|
||||
const campaigns = [
|
||||
{
|
||||
code: 'CAM-98231',
|
||||
name: 'Summer Sale 2024',
|
||||
audienceLabel: '45,200 recipients',
|
||||
audienceGroup: 'Retail subscribers',
|
||||
status: 'Sent',
|
||||
totalRecipients: 48250,
|
||||
deliveredCount: 47482,
|
||||
readCount: 30987,
|
||||
failedCount: 578,
|
||||
deliveryRate: 98.4,
|
||||
readRate: 64.2,
|
||||
sentAt,
|
||||
templateName: 'summer_promo_v2',
|
||||
language: 'English (US)',
|
||||
messageTitle: 'Hi {{name}}, ☀️',
|
||||
messageBody: 'Our Summer Sale is here! Get up to 40% OFF on all new arrivals. Use code SUMMER40 at checkout.',
|
||||
primaryButton: 'Shop Collection',
|
||||
secondaryButton: 'View Catalog',
|
||||
bannerImageUrl: 'https://lh3.googleusercontent.com/aida-public/AB6AXuDEStTHrI49NhOpgRMdXx3saVUtVNe9fBtTvDiMZMeuDcQNU8eJHfAxc5hS5M8ligofVNNpUi59-kOLD9peg5njH1bWmsrHGXIx7A37_pAFEfxEAGVbjVjWCD0mGWIHu4LIShS9yDlFmvznUPzlye_JNLPzs7S8LIULMi-bL7cP6qt-uzXKuoWUwj1sw0uq0UcJnkCb6Y-04pNG8iNd2MINCbLOSbmRyf8OSOe1b9-u-sA6p5Mq3CKRjP-Fvk0vk3ZKdritVLiB0U8',
|
||||
recipients: [
|
||||
{ phoneNumber: '+1 (555) 012-3456', status: 'Read', sentAt: new Date('2024-07-15T10:12:00.000Z'), deviceOs: 'Android' },
|
||||
{ phoneNumber: '+1 (555) 012-7890', status: 'Delivered', sentAt: new Date('2024-07-15T09:48:00.000Z'), deviceOs: 'iOS' },
|
||||
{ phoneNumber: '+1 (555) 013-1122', status: 'Failed', sentAt: new Date('2024-07-15T09:45:00.000Z'), errorReason: 'Policy Violation', deviceOs: 'Android' },
|
||||
{ phoneNumber: '+1 (555) 014-3344', status: 'Read', sentAt: new Date('2024-07-15T10:05:00.000Z'), deviceOs: 'Android' },
|
||||
{ phoneNumber: '+1 (555) 015-5566', status: 'Delivered', sentAt: new Date('2024-07-15T09:52:00.000Z'), deviceOs: 'iOS' },
|
||||
],
|
||||
},
|
||||
{
|
||||
code: 'CAM-98244',
|
||||
name: 'Weekly Newsletter #42',
|
||||
audienceLabel: 'VIP Customer List',
|
||||
audienceGroup: 'High-value segment',
|
||||
status: 'Scheduled',
|
||||
totalRecipients: 18640,
|
||||
deliveredCount: 0,
|
||||
readCount: 0,
|
||||
failedCount: 0,
|
||||
deliveryRate: null,
|
||||
readRate: null,
|
||||
scheduledAt: new Date('2024-07-16T14:00:00.000Z'),
|
||||
templateName: 'vip_newsletter_v42',
|
||||
language: 'English (US)',
|
||||
messageTitle: 'Your insider update is almost here',
|
||||
messageBody: 'A curated digest for premium customers with fresh offers and product stories.',
|
||||
primaryButton: 'Open Newsletter',
|
||||
secondaryButton: 'Manage Preferences',
|
||||
bannerImageUrl: 'https://images.unsplash.com/photo-1520607162513-77705c0f0d4a?auto=format&fit=crop&w=800&q=80',
|
||||
recipients: [],
|
||||
},
|
||||
{
|
||||
code: 'CAM-98255',
|
||||
name: 'Product Launch Promo',
|
||||
audienceLabel: 'New Leads Segment',
|
||||
audienceGroup: 'Cold outreach',
|
||||
status: 'Draft',
|
||||
totalRecipients: 9300,
|
||||
deliveredCount: 0,
|
||||
readCount: 0,
|
||||
failedCount: 0,
|
||||
deliveryRate: 0,
|
||||
readRate: 0,
|
||||
templateName: 'launch_teaser_v1',
|
||||
language: 'English (US)',
|
||||
messageTitle: 'Be first to see the launch',
|
||||
messageBody: 'A teaser sequence for high-intent prospects before the public product announcement.',
|
||||
primaryButton: 'Join Waitlist',
|
||||
secondaryButton: 'See Features',
|
||||
bannerImageUrl: 'https://images.unsplash.com/photo-1516321318423-f06f85e504b3?auto=format&fit=crop&w=800&q=80',
|
||||
recipients: [],
|
||||
},
|
||||
{
|
||||
code: 'CAM-98201',
|
||||
name: 'Loyalty Program Update',
|
||||
audienceLabel: 'Dormant Users',
|
||||
audienceGroup: 'Reactivation list',
|
||||
status: 'Failed',
|
||||
totalRecipients: 60700,
|
||||
deliveredCount: 27315,
|
||||
readCount: 10844,
|
||||
failedCount: 33385,
|
||||
deliveryRate: 45,
|
||||
readRate: 17.9,
|
||||
sentAt: new Date('2024-07-10T08:30:00.000Z'),
|
||||
templateName: 'loyalty_reactivation_v1',
|
||||
language: 'English (US)',
|
||||
messageTitle: 'We saved your rewards for you',
|
||||
messageBody: 'A recovery campaign for inactive users with points reminder and welcome-back offer.',
|
||||
primaryButton: 'Claim Rewards',
|
||||
secondaryButton: 'Need Help',
|
||||
bannerImageUrl: 'https://images.unsplash.com/photo-1515169067868-5387ec356754?auto=format&fit=crop&w=800&q=80',
|
||||
recipients: [],
|
||||
},
|
||||
];
|
||||
|
||||
async function main() {
|
||||
for (const campaign of campaigns) {
|
||||
await prisma.campaign.upsert({
|
||||
where: { code: campaign.code },
|
||||
update: {
|
||||
name: campaign.name,
|
||||
audienceLabel: campaign.audienceLabel,
|
||||
audienceGroup: campaign.audienceGroup,
|
||||
status: campaign.status,
|
||||
totalRecipients: campaign.totalRecipients,
|
||||
deliveredCount: campaign.deliveredCount,
|
||||
readCount: campaign.readCount,
|
||||
failedCount: campaign.failedCount,
|
||||
deliveryRate: campaign.deliveryRate,
|
||||
readRate: campaign.readRate,
|
||||
sentAt: campaign.sentAt || null,
|
||||
scheduledAt: campaign.scheduledAt || null,
|
||||
templateName: campaign.templateName,
|
||||
language: campaign.language,
|
||||
messageTitle: campaign.messageTitle,
|
||||
messageBody: campaign.messageBody,
|
||||
primaryButton: campaign.primaryButton,
|
||||
secondaryButton: campaign.secondaryButton,
|
||||
bannerImageUrl: campaign.bannerImageUrl,
|
||||
},
|
||||
create: {
|
||||
id: randomUUID(),
|
||||
code: campaign.code,
|
||||
name: campaign.name,
|
||||
audienceLabel: campaign.audienceLabel,
|
||||
audienceGroup: campaign.audienceGroup,
|
||||
status: campaign.status,
|
||||
totalRecipients: campaign.totalRecipients,
|
||||
deliveredCount: campaign.deliveredCount,
|
||||
readCount: campaign.readCount,
|
||||
failedCount: campaign.failedCount,
|
||||
deliveryRate: campaign.deliveryRate,
|
||||
readRate: campaign.readRate,
|
||||
sentAt: campaign.sentAt || null,
|
||||
scheduledAt: campaign.scheduledAt || null,
|
||||
templateName: campaign.templateName,
|
||||
language: campaign.language,
|
||||
messageTitle: campaign.messageTitle,
|
||||
messageBody: campaign.messageBody,
|
||||
primaryButton: campaign.primaryButton,
|
||||
secondaryButton: campaign.secondaryButton,
|
||||
bannerImageUrl: campaign.bannerImageUrl,
|
||||
recipients: {
|
||||
create: campaign.recipients.map((recipient) => ({
|
||||
id: randomUUID(),
|
||||
phoneNumber: recipient.phoneNumber,
|
||||
status: recipient.status,
|
||||
sentAt: recipient.sentAt || null,
|
||||
errorReason: recipient.errorReason || null,
|
||||
deviceOs: recipient.deviceOs || null,
|
||||
})),
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log(`Seeded ${campaigns.length} campaigns.`);
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
Reference in New Issue
Block a user