import { schema } from 'nexus' import { Offense as OffenseType, OffenseWhereInput, OffenseOrderByInput, } from 'nexus-plugin-prisma/client' import { prismaClient as prisma } from '../../prismaClient' import { send as sendNotification } from '../../utils/notification' import { logger } from '../../utils/logger' import * as Auth from '../../utils/auth' const OFFENSE_FIELDS = { id: true, description: true, isDraft: true, message: true, category: true, property: { select: { users: true, owners: true, address: true, }, }, rule: { select: { title: true, }, }, project: { select: { id: true, name: true, managingCompany: { select: { shortHand: true, longName: true, email: true, phone: { select: { number: true, }, }, address: { select: { address1: true, country: true, zip: true, city: true, apartmentNumber: true, state: true, }, }, logo: { select: { url: true, }, }, users: { select: { id: true, }, }, }, }, property: { select: { id: true, address: { select: { id: true, apartmentNumber: true, }, }, users: { select: { id: true, }, }, owners: { select: { id: true, }, }, }, }, }, }, } export const Offense = schema.objectType({ name: 'Offense', definition(t) { t.model.id() t.model.createdAt() t.model.updatedAt() t.model.status() t.model.description() t.model.message() t.model.isSent() t.model.sentAt() t.model.openAt() t.model.isDraft() t.model.createdBy() t.model.picture() t.model.project() t.model.property() t.model.rule() t.model.pictures() t.model.usersUserReceivedOffenses() }, }) export const OffenseMutation = schema.extendType({ type: 'Mutation', definition: (t) => { t.crud.deleteOneOffense({ alias: 'deleteOffense' }) t.crud.updateOneOffense({ alias: 'updateOffense' }) t.crud.createOneOffense({ alias: 'createOffense' }) t.field('createOffense', { type: 'Offense', args: { data: schema.arg({ type: 'OffenseCreateInput' }), }, resolve: async (parent, { data }, ctx: NexusContext) => { const createdOffense = await ctx.prisma.offense.create({ data: { ...data }, select: { id: true, description: true, isDraft: true, message: true, rule: { select: { title: true, }, }, project: { select: { id: true, name: true, managingCompany: { select: { shortName: true, longName: true, email: true, phone: { select: { number: true, }, }, address: { select: { address1: true, country: true, zip: true, city: true, apartmentNumber: true, state: true, }, }, logo: { select: { url: true, }, }, users: true, }, }, }, }, property: { select: { id: true, address: { select: { id: true, apartmentNumber: true, }, }, users: true, owners: true, }, }, }, }) if (!createdOffense.isDraft) { try { await sendNotification({ noAppNotification: true, users: [...createdOffense.property.users, ...createdOffense.property.owners], projectId: createdOffense.project.id, title: 'New offense', titleFr: 'Nouvelle amende', subtitle: createdOffense.rule ? createdOffense.rule.title : '', message: createdOffense.message, type: 'NEW_OFFENSE', data: createdOffense, }).then(() => prisma.offense.update({ where: { id: createdOffense.id }, data: { status: 'SENT', sentAt: new Date() }, }) ) } catch (e) { logger.error(e) } } return (createdOffense as unknown) as OffenseType }, }) /** * UPDATE OFFENSE */ t.field('updateOffense', { type: 'Offense', args: { data: schema.arg({ type: 'OffenseUpdateInput' }), where: schema.arg({ type: 'OffenseWhereUniqueInput' }), }, resolve: async (parent, { where, data }, ctx: NexusContext) => { const currentUserId = Auth.getUserId(ctx) const [currentUser, updatedOffense, oldOffense] = await Promise.all([ ctx.prisma.user.findOne({ where: { id: currentUserId } }), ctx.prisma.offense.update({ where, data, select: OFFENSE_FIELDS }), ctx.prisma.offense.findOne({ where, select: OFFENSE_FIELDS }), ]) try { // Send notification to residents if ( currentUser.role === 'MANAGER' && updatedOffense.property && !updatedOffense.isDraft ) { // The offense is no longer a draft and has been sent! if (oldOffense.isDraft && !updatedOffense.isDraft) { await sendNotification({ noAppNotification: true, users: [...updatedOffense.property.users, ...updatedOffense.property.owners], projectId: updatedOffense.project.id, title: 'New offense', titleFr: 'Nouvelle amende', subtitle: updatedOffense.rule ? updatedOffense.rule.title : '', message: updatedOffense.message, type: 'NEW_OFFENSE', data: updatedOffense, }) } // Else, it's just an update on a offense, also notify the user else { await sendNotification({ noAppNotification: true, users: updatedOffense.property ? [...updatedOffense.property.users, ...updatedOffense.property.owners] : [], projectId: updatedOffense.project.id, title: 'Offense update', titleFr: "Mise à jour d'une amende", subtitle: `${updatedOffense.category}${ updatedOffense.property ? `- #${updatedOffense.property.address.apartmentNumber}` : '' }`, message: 'Go see the changes in the Walter platform.', messageFr: "Allez consulter les changements dans l'application Walter.", type: 'UPDATE_OFFENSE', data: updatedOffense, }) } } } catch (error) { logger.error(error) } return ctx.prisma.offense.findOne({ where: { id: updatedOffense.id } }) }, }) }, }) export const OffenseQuery = schema.extendType({ type: 'Query', definition(t) { t.crud.offense() t.crud.offenses({ filtering: true, ordering: true }) t.field('offenses', { type: 'Offense', list: true, args: { where: schema.arg({ type: 'OffenseWhereInput' }), orderBy: schema.arg({ type: 'OffenseOrderByInput', list: true }), first: schema.arg({ type: 'Int' }), skip: schema.arg({ type: 'Int' }), }, resolve: async ( parent, { where, orderBy, first, skip, }: { where?: OffenseWhereInput orderBy?: OffenseOrderByInput[] first?: number skip?: number }, ctx: NexusContext ) => { return ctx.prisma.offense.findMany({ where, skip, take: first, ...(orderBy?.length > 0 && { orderBy: orderBy[0] }), }) }, }) }, })