update account creation fileds
This commit is contained in:
@@ -322,6 +322,31 @@ export function updateAdminRole(id: string, role: string) {
|
||||
return prisma.adminUser.update({ where: { id }, data: { role: role as any } })
|
||||
}
|
||||
|
||||
export function updateAdmin(
|
||||
id: string,
|
||||
data: {
|
||||
email?: string
|
||||
firstName?: string
|
||||
lastName?: string
|
||||
role?: string
|
||||
passwordHash?: string
|
||||
isActive?: boolean
|
||||
},
|
||||
) {
|
||||
return prisma.adminUser.update({
|
||||
where: { id },
|
||||
data: {
|
||||
...(data.email !== undefined ? { email: data.email } : {}),
|
||||
...(data.firstName !== undefined ? { firstName: data.firstName } : {}),
|
||||
...(data.lastName !== undefined ? { lastName: data.lastName } : {}),
|
||||
...(data.role !== undefined ? { role: data.role as any } : {}),
|
||||
...(data.passwordHash !== undefined ? { passwordHash: data.passwordHash } : {}),
|
||||
...(data.isActive !== undefined ? { isActive: data.isActive } : {}),
|
||||
},
|
||||
include: { permissions: true },
|
||||
})
|
||||
}
|
||||
|
||||
export async function replaceAdminPermissions(id: string, permissions: any[]) {
|
||||
await prisma.adminUser.findUniqueOrThrow({ where: { id } })
|
||||
await prisma.$transaction([
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
companiesQuerySchema, rentersQuerySchema, auditLogQuerySchema, billingQuerySchema, notificationsQuerySchema,
|
||||
invoicesQuerySchema, adminCompanyUpdateSchema, companyStatusSchema,
|
||||
createAdminSchema, adminRoleSchema, adminPermissionsSchema,
|
||||
updateAdminSchema,
|
||||
homepageUpdateSchema, idParamSchema, companyIdParamSchema, billingAccountIdParamSchema, invoiceIdParamSchema,
|
||||
pricingUpdateSchema, planFeatureCreateSchema, planFeatureUpdateSchema, planFeatureIdParamSchema,
|
||||
promotionCreateSchema, promotionUpdateSchema, promotionIdParamSchema,
|
||||
@@ -188,6 +189,13 @@ router.post('/admins', requireAdminAuth, requireAdminRole('SUPER_ADMIN'), async
|
||||
} catch (err) { next(err) }
|
||||
})
|
||||
|
||||
router.patch('/admins/:id', requireAdminAuth, requireAdminRole('SUPER_ADMIN'), async (req, res, next) => {
|
||||
try {
|
||||
const { id } = parseParams(idParamSchema, req)
|
||||
ok(res, await service.updateAdmin(id, parseBody(updateAdminSchema, req)))
|
||||
} catch (err) { next(err) }
|
||||
})
|
||||
|
||||
router.patch('/admins/:id/role', requireAdminAuth, requireAdminRole('SUPER_ADMIN'), async (req, res, next) => {
|
||||
try {
|
||||
const { id } = parseParams(idParamSchema, req)
|
||||
|
||||
@@ -71,14 +71,23 @@ export const permissionSchema = z.object({
|
||||
})
|
||||
|
||||
export const createAdminSchema = z.object({
|
||||
email: z.string().email(),
|
||||
firstName: z.string(),
|
||||
lastName: z.string(),
|
||||
email: z.string().email().trim().toLowerCase(),
|
||||
firstName: z.string().min(1).max(100).trim(),
|
||||
lastName: z.string().min(1).max(100).trim(),
|
||||
role: z.enum(['SUPER_ADMIN', 'ADMIN', 'SUPPORT', 'FINANCE', 'VIEWER']),
|
||||
password: z.string().min(8),
|
||||
permissions: z.array(permissionSchema).optional(),
|
||||
})
|
||||
|
||||
export const updateAdminSchema = z.object({
|
||||
email: z.string().email().trim().toLowerCase().optional(),
|
||||
firstName: z.string().min(1).max(100).trim().optional(),
|
||||
lastName: z.string().min(1).max(100).trim().optional(),
|
||||
role: z.enum(['SUPER_ADMIN', 'ADMIN', 'SUPPORT', 'FINANCE', 'VIEWER']).optional(),
|
||||
password: z.string().min(8).optional(),
|
||||
isActive: z.boolean().optional(),
|
||||
})
|
||||
|
||||
export const adminRoleSchema = z.object({
|
||||
role: z.enum(['SUPER_ADMIN', 'ADMIN', 'SUPPORT', 'FINANCE', 'VIEWER']),
|
||||
})
|
||||
|
||||
@@ -216,6 +216,29 @@ export async function createAdmin(body: { email: string; firstName: string; last
|
||||
return presenter.presentAdminUser(admin)
|
||||
}
|
||||
|
||||
export async function updateAdmin(
|
||||
id: string,
|
||||
body: {
|
||||
email?: string
|
||||
firstName?: string
|
||||
lastName?: string
|
||||
role?: string
|
||||
password?: string
|
||||
isActive?: boolean
|
||||
},
|
||||
) {
|
||||
const admin = await repo.updateAdmin(id, {
|
||||
...(body.email !== undefined ? { email: body.email } : {}),
|
||||
...(body.firstName !== undefined ? { firstName: body.firstName } : {}),
|
||||
...(body.lastName !== undefined ? { lastName: body.lastName } : {}),
|
||||
...(body.role !== undefined ? { role: body.role } : {}),
|
||||
...(body.isActive !== undefined ? { isActive: body.isActive } : {}),
|
||||
...(body.password ? { passwordHash: await bcrypt.hash(body.password, 12) } : {}),
|
||||
})
|
||||
|
||||
return presenter.presentAdminUser(admin)
|
||||
}
|
||||
|
||||
export function updateAdminRole(id: string, role: string) {
|
||||
return repo.updateAdminRole(id, role)
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@ type DbClient = Pick<typeof prisma, 'company' | 'brandSettings' | 'contractSetti
|
||||
|
||||
type CompanySignupInput = {
|
||||
companyName: string
|
||||
legalName: string
|
||||
slug: string
|
||||
email: string
|
||||
ownerEmail: string
|
||||
companyEmail: string
|
||||
companyPhone: string
|
||||
streetAddress: string
|
||||
city: string
|
||||
@@ -13,8 +15,21 @@ type CompanySignupInput = {
|
||||
zipCode: string
|
||||
legalForm: string
|
||||
managerName: string
|
||||
iceNumber: string
|
||||
taxId: string
|
||||
operatingLicenseNumber: string
|
||||
operatingLicenseIssuedAt: string
|
||||
operatingLicenseIssuedBy: string
|
||||
fax?: string
|
||||
yearsActive: string
|
||||
representativeName?: string
|
||||
representativeTitle?: string
|
||||
responsibleName: string
|
||||
responsibleRole: string
|
||||
responsibleIdentityNumber: string
|
||||
responsibleQualification?: string
|
||||
responsiblePhone: string
|
||||
responsibleEmail: string
|
||||
currency: 'MAD'
|
||||
registrationNumber: string
|
||||
plan: 'STARTER' | 'GROWTH' | 'PRO'
|
||||
@@ -44,17 +59,31 @@ export async function createCompanySignup(db: DbClient, input: CompanySignupInpu
|
||||
data: {
|
||||
name: input.companyName,
|
||||
slug: input.slug,
|
||||
email: input.email,
|
||||
email: input.companyEmail,
|
||||
phone: input.companyPhone,
|
||||
address: {
|
||||
streetAddress: input.streetAddress,
|
||||
city: input.city,
|
||||
country: input.country,
|
||||
zipCode: input.zipCode,
|
||||
legalName: input.legalName,
|
||||
legalForm: input.legalForm,
|
||||
companyEmail: input.companyEmail,
|
||||
managerName: input.managerName,
|
||||
iceNumber: input.iceNumber,
|
||||
operatingLicenseNumber: input.operatingLicenseNumber,
|
||||
operatingLicenseIssuedAt: input.operatingLicenseIssuedAt,
|
||||
operatingLicenseIssuedBy: input.operatingLicenseIssuedBy,
|
||||
fax: input.fax || null,
|
||||
yearsActive: input.yearsActive,
|
||||
representativeName: input.representativeName || null,
|
||||
representativeTitle: input.representativeTitle || null,
|
||||
responsibleName: input.responsibleName,
|
||||
responsibleRole: input.responsibleRole,
|
||||
responsibleIdentityNumber: input.responsibleIdentityNumber,
|
||||
responsibleQualification: input.responsibleQualification || null,
|
||||
responsiblePhone: input.responsiblePhone,
|
||||
responsibleEmail: input.responsibleEmail,
|
||||
},
|
||||
status: 'TRIALING',
|
||||
},
|
||||
@@ -65,7 +94,7 @@ export async function createCompanySignup(db: DbClient, input: CompanySignupInpu
|
||||
companyId: company.id,
|
||||
displayName: input.companyName,
|
||||
subdomain: input.slug,
|
||||
publicEmail: input.email,
|
||||
publicEmail: input.companyEmail,
|
||||
publicPhone: input.companyPhone,
|
||||
publicAddress: input.streetAddress,
|
||||
publicCity: input.city,
|
||||
@@ -78,8 +107,9 @@ export async function createCompanySignup(db: DbClient, input: CompanySignupInpu
|
||||
await db.contractSettings.create({
|
||||
data: {
|
||||
companyId: company.id,
|
||||
legalName: input.companyName,
|
||||
legalName: input.legalName,
|
||||
registrationNumber: input.registrationNumber,
|
||||
taxId: input.taxId,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -103,7 +133,7 @@ export async function createCompanySignup(db: DbClient, input: CompanySignupInpu
|
||||
clerkUserId: `local_owner_${company.id}`,
|
||||
firstName: input.firstName,
|
||||
lastName: input.lastName,
|
||||
email: input.email,
|
||||
email: input.ownerEmail,
|
||||
phone: input.companyPhone,
|
||||
passwordHash: input.passwordHash,
|
||||
role: 'OWNER',
|
||||
|
||||
@@ -6,15 +6,30 @@ export const companySignupSchema = z.object({
|
||||
email: z.string().email(),
|
||||
password: z.string().min(8).max(128),
|
||||
companyName: z.string().min(2).max(120),
|
||||
legalName: z.string().min(2).max(160),
|
||||
legalForm: z.string().min(1).max(80),
|
||||
registrationNumber: z.string().min(1).max(120),
|
||||
iceNumber: z.string().min(1).max(120),
|
||||
taxId: z.string().min(1).max(120),
|
||||
operatingLicenseNumber: z.string().min(1).max(120),
|
||||
operatingLicenseIssuedAt: z.string().min(1).max(40),
|
||||
operatingLicenseIssuedBy: z.string().min(1).max(160),
|
||||
streetAddress: z.string().min(1).max(200),
|
||||
city: z.string().min(1).max(120),
|
||||
country: z.string().min(1).max(120),
|
||||
zipCode: z.string().min(1).max(40),
|
||||
companyPhone: z.string().min(1).max(80),
|
||||
companyEmail: z.string().email(),
|
||||
fax: z.string().max(80).optional(),
|
||||
yearsActive: z.string().min(1).max(80),
|
||||
representativeName: z.string().max(160).optional(),
|
||||
representativeTitle: z.string().max(120).optional(),
|
||||
responsibleName: z.string().min(1).max(160),
|
||||
responsibleRole: z.string().min(1).max(120),
|
||||
responsibleIdentityNumber: z.string().min(1).max(120),
|
||||
responsibleQualification: z.string().max(200).optional(),
|
||||
responsiblePhone: z.string().min(1).max(80),
|
||||
responsibleEmail: z.string().email(),
|
||||
preferredLanguage: z.enum(['en', 'fr', 'ar']).default('en'),
|
||||
plan: z.enum(['STARTER', 'GROWTH', 'PRO']),
|
||||
billingPeriod: z.enum(['MONTHLY', 'ANNUAL']),
|
||||
|
||||
@@ -32,12 +32,12 @@ async function generateUniqueSlug(baseName: string) {
|
||||
}
|
||||
|
||||
export async function signup(body: CompanySignupInput) {
|
||||
if (await repo.findCompanyByEmail(body.email)) {
|
||||
throw new AppError('A company account with this email already exists', 409, 'email_taken')
|
||||
if (await repo.findCompanyByEmail(body.companyEmail)) {
|
||||
throw new AppError('A company account with this contact email already exists', 409, 'company_email_taken')
|
||||
}
|
||||
|
||||
if (await repo.findEmployeeByEmail(body.email)) {
|
||||
throw new AppError('An employee account with this email already exists', 409, 'email_taken')
|
||||
throw new AppError('An employee account with this owner email already exists', 409, 'owner_email_taken')
|
||||
}
|
||||
|
||||
const slug = await generateUniqueSlug(body.companyName)
|
||||
@@ -47,8 +47,10 @@ export async function signup(body: CompanySignupInput) {
|
||||
|
||||
const result = await prisma.$transaction((tx) => repo.createCompanySignup(tx, {
|
||||
companyName: body.companyName,
|
||||
legalName: body.legalName,
|
||||
slug,
|
||||
email: body.email,
|
||||
ownerEmail: body.email,
|
||||
companyEmail: body.companyEmail,
|
||||
companyPhone: body.companyPhone,
|
||||
streetAddress: body.streetAddress,
|
||||
city: body.city,
|
||||
@@ -56,8 +58,21 @@ export async function signup(body: CompanySignupInput) {
|
||||
zipCode: body.zipCode,
|
||||
legalForm: body.legalForm,
|
||||
managerName: `${body.firstName} ${body.lastName}`.trim(),
|
||||
iceNumber: body.iceNumber,
|
||||
taxId: body.taxId,
|
||||
operatingLicenseNumber: body.operatingLicenseNumber,
|
||||
operatingLicenseIssuedAt: body.operatingLicenseIssuedAt,
|
||||
operatingLicenseIssuedBy: body.operatingLicenseIssuedBy,
|
||||
fax: body.fax,
|
||||
yearsActive: body.yearsActive,
|
||||
representativeName: body.representativeName,
|
||||
representativeTitle: body.representativeTitle,
|
||||
responsibleName: body.responsibleName,
|
||||
responsibleRole: body.responsibleRole,
|
||||
responsibleIdentityNumber: body.responsibleIdentityNumber,
|
||||
responsibleQualification: body.responsibleQualification,
|
||||
responsiblePhone: body.responsiblePhone,
|
||||
responsibleEmail: body.responsibleEmail,
|
||||
currency: body.currency,
|
||||
registrationNumber: body.registrationNumber,
|
||||
plan: body.plan,
|
||||
|
||||
Reference in New Issue
Block a user