import { schema } from 'nexus' import { send as sendNotifications } from '../../utils/notification' import { logger } from '../../utils/logger' import * as Auth from '../../utils/auth' import GeneralUtils from '../../utils/general' const SERVICE_REQUEST_FIELDS = { id: true, category: true, description: true, isDraft: true, status: 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: { select: { id: true, }, }, }, }, }, }, assignedTo: { select: { id: true, }, }, property: { select: { id: true, address: { select: { id: true, apartmentNumber: true, }, }, users: { select: { id: true, }, }, owners: { select: { id: true, }, }, }, }, } export const ServiceRequest = schema.objectType({ name: 'ServiceRequest', definition(t) { t.model.id() t.model.status() t.model.createdAt() t.model.updatedAt() t.model.category() t.model.description() t.model.isCommonArea() t.model.residentWantsToBeThere() t.model.isDraft() t.model.identificationNumber() t.model.assignedTo() t.model.associatedTo() t.model.createdBy() t.model.priority() t.model.project() t.model.property() t.model.comments() t.model.pictures() t.model.seenBy() }, }) export const ServiceRequestQueries = schema.extendType({ type: 'Query', definition(t) { t.crud.serviceRequest() t.crud.serviceRequests({ filtering: true, ordering: true }) }, }) export const ServiceRequestMutation = schema.extendType({ type: 'Mutation', definition: (t) => { t.crud.deleteOneServiceRequest({ alias: 'deleteServiceRequest' }) t.crud.updateOneServiceRequest({ alias: 'updateServiceRequest' }) t.crud.createOneServiceRequest({ alias: 'createServiceRequest' }) /** * CREATE SERVICE REQUEST */ t.field('createServiceRequest', { type: 'ServiceRequest', args: { data: schema.arg({ type: 'ServiceRequestCreateInput' }), }, resolve: async (parent, { data }, ctx: NexusContext) => { const currentUserId = Auth.getUserId(ctx) const [currentUser, createdServiceRequest] = await Promise.all([ ctx.prisma.user.findOne({ where: { id: currentUserId } }), ctx.prisma.serviceRequest.create({ data: { ...data, createdBy: { connect: { id: currentUserId, }, }, }, select: SERVICE_REQUEST_FIELDS, }), ]) if (currentUser.role === 'RESIDENT') { try { // Send notification to residents and/or managers await sendNotifications({ users: createdServiceRequest.project.managingCompany.users, projectId: createdServiceRequest.project.id, title: `New work order created for unit #${ createdServiceRequest.property.address.apartmentNumber } by ${GeneralUtils.getUserName(currentUser)}.`, titleFr: `Nouvelle demande de service crée pour l'unité #${ createdServiceRequest.property.address.apartmentNumber } par ${GeneralUtils.getUserName(currentUser)}.`, message: 'Get more detail, change the work order, assign it to someone all on the Walter plateform. https://manager.usewalter.com', messageFr: "Consultez les détails, faites le suivi de la demande et assigné la à quelq'un sur la plate-forme Walter. https://manager.usewalter.com", type: 'NEW_SERVICE_REQUEST', data: { id: createdServiceRequest.id, }, }) } catch (error) { logger.error(error) } } // Created by property manager so we send to residents else { if (!createdServiceRequest.isDraft) { try { // Send notification to residents if (createdServiceRequest.property) { sendNotifications({ users: [ ...createdServiceRequest.property.users, ...createdServiceRequest.property.owners, ], projectId: createdServiceRequest.project.id, title: `New work order created for your unit #${createdServiceRequest.property.address.apartmentNumber}.`, titleFr: `Nouvelle demande de service pour votre unité #${createdServiceRequest.property.address.apartmentNumber}.`, message: 'Follow the work order status and get more details about it in the Walter app.', messageFr: "Suivez le status de la demande et consultez les détails de celle-ci dans l'application Walter.", type: 'NEW_SERVICE_REQUEST', data: { id: createdServiceRequest.id, }, }).catch(logger.error) } // Notification to assigne if (createdServiceRequest.assignedTo) { sendNotifications({ users: [createdServiceRequest.assignedTo], projectId: createdServiceRequest.project.id, title: "You've been assigned to a work order", message: `${createdServiceRequest.category || ''}${ createdServiceRequest.property ? ` - #${createdServiceRequest.property.address.apartmentNumber}` : '' }`, type: 'SERVICE_REQUEST_ASSIGNED', data: createdServiceRequest, }).catch(logger.error) } } catch (error) { logger.error(error) } } } return ctx.prisma.serviceRequest.findOne({ where: { id: createdServiceRequest.id } }) }, }) /** * UPDATE SERVICE REQUEST */ t.field('updateServiceRequest', { type: 'ServiceRequest', args: { data: schema.arg({ type: 'ServiceRequestUpdateInput' }), where: schema.arg({ type: 'ServiceRequestWhereUniqueInput' }), }, resolve: async (parent, { where, data }, ctx: NexusContext) => { const currentUserId = Auth.getUserId(ctx) const [currentUser, updatedServiceRequest, oldServiceRequest] = await Promise.all([ ctx.prisma.user.findOne({ where: { id: currentUserId } }), ctx.prisma.serviceRequest.update({ where, data, select: SERVICE_REQUEST_FIELDS }), ctx.prisma.serviceRequest.findOne({ where, select: SERVICE_REQUEST_FIELDS }), ]) try { // It's no more a draft! if (currentUser.role === 'MANAGER' && !updatedServiceRequest.isDraft) { // New assignee if ( (updatedServiceRequest.assignedTo && !oldServiceRequest.assignedTo) || (updatedServiceRequest.assignedTo && oldServiceRequest.assignedTo && updatedServiceRequest.assignedTo.id !== oldServiceRequest.assignedTo.id) ) { sendNotifications({ users: [updatedServiceRequest.assignedTo], projectId: updatedServiceRequest.project.id, title: "You've been assigned to a work order", message: `${updatedServiceRequest.category || ''}${ updatedServiceRequest.property ? `- #${updatedServiceRequest.property.address.apartmentNumber}` : '' }`, type: 'SERVICE_REQUEST_ASSIGNED', data: { id: updatedServiceRequest.id, }, }).catch(logger.error) } // Send notification to residents if (updatedServiceRequest.property) { // The service request is no longer a draft and has been sent! if (oldServiceRequest.isDraft && !updatedServiceRequest.isDraft) { await sendNotifications({ users: [ ...updatedServiceRequest.property.users, ...updatedServiceRequest.property.owners, ], projectId: updatedServiceRequest.project.id, title: `New work order created for your unit #${updatedServiceRequest.property.address.apartmentNumber}.`, titleFr: `Nouvelle demande de service pour votre unité #${updatedServiceRequest.property.address.apartmentNumber}.`, message: 'Follow the work order status and get more details about it in the Walter app.', messageFr: "Suivez le status de la demande et consultez les détails de celle-ci dans l'application Walter.", type: 'NEW_SERVICE_REQUEST', data: { id: updatedServiceRequest.id, }, }) } // Else, status change? else if (updatedServiceRequest.status !== oldServiceRequest.status) { await sendNotifications({ users: updatedServiceRequest.property ? [ ...updatedServiceRequest.property.users, ...updatedServiceRequest.property.owners, ] : [], projectId: updatedServiceRequest.project.id, title: 'Work order update', titleFr: "Mise à jour d'une demande service", subtitle: `${updatedServiceRequest.category}${ updatedServiceRequest.property ? `- #${updatedServiceRequest.property.address.apartmentNumber}` : '' }`, message: 'Go see the changes in the Walter platform.', messageFr: "Allez consulter les changements dans l'application Walter.", type: 'UPDATE_SERVICE_REQUEST', data: { id: updatedServiceRequest.id, }, }) } } } } catch (error) { logger.error(error) } return ctx.prisma.serviceRequest.findOne({ where: { id: updatedServiceRequest.id } }) }, }) }, })