Initial commit: OnDeck project

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
lorentz 2026-02-18 13:20:52 +00:00
commit b036a93da2
139 changed files with 33198 additions and 0 deletions

View file

@ -0,0 +1,72 @@
import { PrismaClient } from '@prisma/client'
import { PrismaPg } from '@prisma/adapter-pg'
import { Pool } from 'pg'
import { config } from 'dotenv'
config() // Load .env file
const pool = new Pool({ connectionString: process.env.DATABASE_URL })
const adapter = new PrismaPg(pool)
const prisma = new PrismaClient({ adapter })
async function createAdminUser(email: string, displayName: string) {
console.log(`Creating admin user: ${email}`)
// Create or update the user
const user = await prisma.user.upsert({
where: { email },
update: {
displayName,
isActive: true,
},
create: {
email,
displayName,
isActive: true,
},
})
console.log(`✅ User created/updated: ${user.id}`)
// Find the Admin role
const adminRole = await prisma.role.findUnique({
where: { name: 'Admin' },
})
if (!adminRole) {
console.error('❌ Admin role not found. Run seed first: npx prisma db seed')
process.exit(1)
}
// Assign Admin role to user
await prisma.userRole.upsert({
where: {
userId_roleId: {
userId: user.id,
roleId: adminRole.id,
},
},
update: {},
create: {
userId: user.id,
roleId: adminRole.id,
},
})
console.log(`✅ Admin role assigned to ${email}`)
console.log('\n🎉 Admin user setup complete!')
console.log(` Email: ${email}`)
console.log(` User ID: ${user.id}`)
}
const email = process.argv[2] || 'lorentz@wulfconsulting.com'
const displayName = process.argv[3] || 'Lorentz'
createAdminUser(email, displayName)
.catch((e) => {
console.error('❌ Failed:', e)
process.exit(1)
})
.finally(async () => {
await prisma.$disconnect()
await pool.end()
})

View file

@ -0,0 +1,131 @@
import { PrismaClient } from '@prisma/client'
import { PrismaPg } from '@prisma/adapter-pg'
import { Pool } from 'pg'
import * as fs from 'fs'
import * as path from 'path'
import * as dotenv from 'dotenv'
// Load environment variables
dotenv.config()
const pool = new Pool({ connectionString: process.env.DATABASE_URL })
const adapter = new PrismaPg(pool)
const prisma = new PrismaClient({ adapter })
interface CsvRow {
task: string
daysAfterRenewal: number
daysPriorToNextRenewal: number
appliesTo: string
active: boolean
}
function parseCsv(content: string): CsvRow[] {
const lines = content.trim().split('\n')
// Skip header row, handle BOM
const dataLines = lines.slice(1)
return dataLines.map((line) => {
const parts = line.split(',')
return {
task: parts[0].trim(),
daysAfterRenewal: parseInt(parts[1].trim()),
daysPriorToNextRenewal: parseInt(parts[2].trim()),
appliesTo: parts[3].trim(),
active: parts[4].trim().toLowerCase() === 'yes',
}
})
}
async function main() {
console.log('Importing SHAPE tasks from CSV...')
// Read CSV file
const csvPath = path.join(__dirname, '../../dev/shapetasks.csv')
const csvContent = fs.readFileSync(csvPath, 'utf-8')
const rows = parseCsv(csvContent)
console.log(`Found ${rows.length} tasks to import`)
// Ensure Shape and Shape2 designations exist
const shapeDesignation = await prisma.designation.upsert({
where: { name: 'Shape' },
update: {},
create: {
name: 'Shape',
description: 'SHAPE program - primary designation for claims workflow tasks',
color: 'designation-indigo',
displayOrder: 10,
isActive: true,
},
})
console.log(`Shape designation ID: ${shapeDesignation.id}`)
const shape2Designation = await prisma.designation.upsert({
where: { name: 'Shape2' },
update: {},
create: {
name: 'Shape2',
description: 'SHAPE program - secondary designation for claims workflow tasks',
color: 'designation-violet',
displayOrder: 11,
isActive: true,
},
})
console.log(`Shape2 designation ID: ${shape2Designation.id}`)
// Import task templates
let created = 0
let skipped = 0
for (let i = 0; i < rows.length; i++) {
const row = rows[i]
const designationId = row.appliesTo === 'Shape'
? shapeDesignation.id
: shape2Designation.id
// Check if template already exists with same name and designation
const existing = await prisma.taskTemplate.findFirst({
where: {
name: row.task,
designationId: designationId,
},
})
if (existing) {
console.log(`Skipping existing: "${row.task}" (${row.appliesTo})`)
skipped++
continue
}
// Create template using PRE_RENEWAL timing with negative offset
await prisma.taskTemplate.create({
data: {
name: row.task,
description: null,
department: 'CLAIMS',
timing: 'PRE_RENEWAL',
daysOffset: -row.daysPriorToNextRenewal, // Negative for pre-renewal
defaultPriority: 'MEDIUM',
isActive: row.active,
displayOrder: i + 1,
designationId: designationId,
},
})
console.log(`Created: "${row.task}" (${row.appliesTo}, ${row.daysPriorToNextRenewal} days before renewal)`)
created++
}
console.log(`\nImport complete: ${created} created, ${skipped} skipped`)
}
main()
.catch((e) => {
console.error('Import failed:', e)
process.exit(1)
})
.finally(async () => {
await prisma.$disconnect()
await pool.end()
})

View file

@ -0,0 +1,22 @@
import 'dotenv/config'
import { runSync } from '../src/lib/sync/sync-engine'
async function main() {
console.log('Starting manual sync...')
const result = await runSync(undefined, false) // Full sync, not incremental
if (result.success) {
console.log('\n✅ Sync completed successfully!')
console.log('Stats:', JSON.stringify(result.stats, null, 2))
} else {
console.error('\n❌ Sync failed:', result.error)
console.log('Stats:', JSON.stringify(result.stats, null, 2))
process.exit(1)
}
}
main().catch((error) => {
console.error('Fatal error:', error)
process.exit(1)
})