Adde schema and route information for all entities.
This commit is contained in:
@@ -72,6 +72,9 @@ Promise.all([
|
|||||||
container.authRoutes = new Routes.AuthRoutes(container)
|
container.authRoutes = new Routes.AuthRoutes(container)
|
||||||
container.userRoutes = new Routes.UserRoutes(container)
|
container.userRoutes = new Routes.UserRoutes(container)
|
||||||
container.assetRoutes = new Routes.AssetRoutes(container)
|
container.assetRoutes = new Routes.AssetRoutes(container)
|
||||||
|
container.workItemRoutes = new Routes.WorkItemRoutes(container)
|
||||||
|
container.teamRoutes = new Routes.TeamRoutes(container)
|
||||||
|
container.activityRoutes = new Routes.ActivityRoutes(container)
|
||||||
|
|
||||||
app.use(function(req, res, next) {
|
app.use(function(req, res, next) {
|
||||||
res.status(404).json({
|
res.status(404).json({
|
||||||
|
|||||||
153
server/src/api/routes/ActivityRoutes.js
Normal file
153
server/src/api/routes/ActivityRoutes.js
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
import passport from 'passport'
|
||||||
|
import createError from 'http-errors'
|
||||||
|
import autobind from 'autobind-decorator'
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
export class ActivityRoutes {
|
||||||
|
constructor(container) {
|
||||||
|
const app = container.app
|
||||||
|
|
||||||
|
this.log = container.log
|
||||||
|
this.db = container.db
|
||||||
|
this.mq = container.mq
|
||||||
|
this.ws = container.ws
|
||||||
|
|
||||||
|
app.route('/activities')
|
||||||
|
.get(passport.authenticate('bearer', { session: false }), this.listActivitys)
|
||||||
|
.post(passport.authenticate('bearer', { session: false }), this.createActivity)
|
||||||
|
.put(passport.authenticate('bearer', { session: false }), this.updateActivity)
|
||||||
|
|
||||||
|
app.route('/activities/:_id([a-f0-9]{24})')
|
||||||
|
.get(passport.authenticate('bearer', { session: false }), this.getActivity)
|
||||||
|
.delete(passport.authenticate('bearer', { session: false }), this.deleteActivity)
|
||||||
|
}
|
||||||
|
|
||||||
|
listActivitys(req, res, next) {
|
||||||
|
const Activity = this.db.Activity
|
||||||
|
let limit = req.params.limit || 20
|
||||||
|
let skip = req.params.skip || 0
|
||||||
|
let partial = !!req.params.partial
|
||||||
|
let branch = req.params.branch
|
||||||
|
let query = {}
|
||||||
|
|
||||||
|
if (branch) {
|
||||||
|
query.branch = branch
|
||||||
|
}
|
||||||
|
|
||||||
|
Activity.count({}).then((total) => {
|
||||||
|
let activities = []
|
||||||
|
let cursor = Activity.find(query).limit(limit).skip(skip).cursor().map((doc) => {
|
||||||
|
return doc.toClient(partial)
|
||||||
|
})
|
||||||
|
|
||||||
|
cursor.on('data', (doc) => {
|
||||||
|
activities.push(doc)
|
||||||
|
})
|
||||||
|
cursor.on('end', () => {
|
||||||
|
res.json({
|
||||||
|
total: total,
|
||||||
|
offset: skip,
|
||||||
|
count: activities.length,
|
||||||
|
items: activities
|
||||||
|
})
|
||||||
|
})
|
||||||
|
cursor.on('error', (err) => {
|
||||||
|
next(createError.InternalServerError(err.message))
|
||||||
|
})
|
||||||
|
}).catch((err) => {
|
||||||
|
next(createError.InternalServerError(err.message))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
createActivity(req, res, next) {
|
||||||
|
const role = req.user.role
|
||||||
|
|
||||||
|
// If user's role is not Executive or Administrator, return an error
|
||||||
|
if (role !== 'executive' && role !== 'administrator') {
|
||||||
|
return next(new createError.Forbidden())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new Activity template then assign it to a value in the req.body
|
||||||
|
const Activity = this.db.Activity
|
||||||
|
let activity = new Activity(req.body)
|
||||||
|
|
||||||
|
// Save the activity (with promise) - If it doesnt, catch and throw error
|
||||||
|
activity.save().then((newActivity) => {
|
||||||
|
res.json(newActivity.toClient())
|
||||||
|
}).catch((err) => {
|
||||||
|
next(createError.InternalServerError(err.message))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
updateActivity(req, res, next) {
|
||||||
|
const role = req.user.role
|
||||||
|
|
||||||
|
// If user's role is not Executive or Administrator, return an error
|
||||||
|
if (role !== 'executive' && role !== 'administrator') {
|
||||||
|
return new createError.Forbidden()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do this here because Mongoose will add it automatically otherwise
|
||||||
|
if (!req.body._id) {
|
||||||
|
return next(createError.BadRequest('No _id given in body'))
|
||||||
|
}
|
||||||
|
|
||||||
|
let Activity = this.db.Activity
|
||||||
|
let activityUpdates = null
|
||||||
|
|
||||||
|
try {
|
||||||
|
activityUpdates = new Activity(req.body)
|
||||||
|
} catch (err) {
|
||||||
|
return next(createError.BadRequest('Invalid data'))
|
||||||
|
}
|
||||||
|
|
||||||
|
Activity.findById(activityUpdates._id).then((foundActivity) => {
|
||||||
|
if (!foundActivity) {
|
||||||
|
return next(createError.NotFound(`Activity with _id ${_id} was not found`))
|
||||||
|
}
|
||||||
|
foundActivity.merge(activityUpdates)
|
||||||
|
return foundActivity.save()
|
||||||
|
}).then((savedActivity) => {
|
||||||
|
res.json(savedActivity.toClient())
|
||||||
|
}).catch((err) => {
|
||||||
|
next(createError.InternalServerError(err.message))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
getActivity(req, res, next) {
|
||||||
|
const Activity = this.db.Activity
|
||||||
|
const _id = req.params._id
|
||||||
|
|
||||||
|
Activity.findById(_id).then((activity) => {
|
||||||
|
if (!activity) {
|
||||||
|
return next(createError.NotFound(`Activity with _id ${_id} not found`))
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json(activity.toClient())
|
||||||
|
}).catch((err) => {
|
||||||
|
next(createError.InternalServerError(err.message))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteActivity(req, res, next) {
|
||||||
|
const role = req.user.role
|
||||||
|
|
||||||
|
// If user's role is not Executive or Administrator, return an error
|
||||||
|
if (role !== 'executive' && role !== 'administrator') {
|
||||||
|
return new createError.Forbidden()
|
||||||
|
}
|
||||||
|
|
||||||
|
const Activity = this.db.Activity
|
||||||
|
const _id = req.params._id
|
||||||
|
|
||||||
|
Activity.remove({ _id }).then((activity) => {
|
||||||
|
if (!activity) {
|
||||||
|
return next(createError.NotFound(`Activity with _id ${_id} not found`))
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json({})
|
||||||
|
}).catch((err) => {
|
||||||
|
next(createError.InternalServerError(err.message))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,493 +0,0 @@
|
|||||||
import passport from 'passport'
|
|
||||||
import createError from 'http-errors'
|
|
||||||
import { makeFingerprint } from '../makeFingerprint'
|
|
||||||
import autobind from 'autobind-decorator'
|
|
||||||
|
|
||||||
@autobind
|
|
||||||
export class ProjectRoutes {
|
|
||||||
constructor(container) {
|
|
||||||
const app = container.app
|
|
||||||
|
|
||||||
this.log = container.log
|
|
||||||
this.db = container.db
|
|
||||||
this.mq = container.mq
|
|
||||||
this.ws = container.ws
|
|
||||||
|
|
||||||
app.route('/projects')
|
|
||||||
.get(passport.authenticate('bearer', { session: false }), this.listProjects)
|
|
||||||
.post(passport.authenticate('bearer', { session: false }), this.createProject)
|
|
||||||
.put(passport.authenticate('bearer', { session: false }), this.updateProject)
|
|
||||||
|
|
||||||
app.route('/projects/:_id([a-f0-9]{24})/broker/:brokerId([a-f0-9]{24})')
|
|
||||||
.get(passport.authenticate('bearer', { session: false }), this.getProjectBrokerClientData)
|
|
||||||
|
|
||||||
app.route('/projects/:_id([a-f0-9]{24})/broker/:brokerId([a-f0-9]{24})/sign-off')
|
|
||||||
.post(passport.authenticate('bearer', { session: false }), this.signOffProjectBrokerClientData)
|
|
||||||
|
|
||||||
app.route('/projects/:projectId([a-f0-9]{24})/create-packages')
|
|
||||||
.post(passport.authenticate('bearer', { session: false }), this.createProjectPackages)
|
|
||||||
|
|
||||||
app.route('/projects/:projectId([a-f0-9]{24})/reset-packages')
|
|
||||||
.post(passport.authenticate('bearer', { session: false }), this.resetProjectPackages)
|
|
||||||
|
|
||||||
app.route('/projects/:projectId([a-f0-9]{24})/build-pdfs')
|
|
||||||
.post(passport.authenticate('bearer', { session: false }), this.buildProjectPDFs)
|
|
||||||
|
|
||||||
app.route('/projects/:_id([a-f0-9]{24})')
|
|
||||||
.get(passport.authenticate('bearer', { session: false }), this.getProject)
|
|
||||||
.delete(passport.authenticate('bearer', { session: false }), this.deleteProject)
|
|
||||||
|
|
||||||
app.route('/projects/import-client-data')
|
|
||||||
.post(passport.authenticate('bearer', { session: false }), this.importProjectClientData)
|
|
||||||
|
|
||||||
app.route('/projects/:_id([a-f0-9]{24})/populated')
|
|
||||||
.get(passport.authenticate('bearer', { session: false }), this.getPopulatedProject)
|
|
||||||
|
|
||||||
app.route('/projects/dashboard')
|
|
||||||
.get(passport.authenticate('bearer', { session: false }), this.listDashboardProjects)
|
|
||||||
|
|
||||||
app.route('/projects/broker/:_id([a-f0-9]{24})')
|
|
||||||
.get(passport.authenticate('bearer', { session: false }), this.listBrokerProjects)
|
|
||||||
}
|
|
||||||
|
|
||||||
listProjects(req, res, next) {
|
|
||||||
const Project = this.db.Project
|
|
||||||
let limit = req.params.limit || 20
|
|
||||||
let skip = req.params.skip || 0
|
|
||||||
let partial = !!req.params.partial
|
|
||||||
let branch = req.params.branch
|
|
||||||
let query = {}
|
|
||||||
|
|
||||||
if (branch) {
|
|
||||||
query.branch = branch
|
|
||||||
}
|
|
||||||
|
|
||||||
Project.count({}).then((total) => {
|
|
||||||
let projects = []
|
|
||||||
let cursor = Project.find(query).limit(limit).skip(skip).cursor().map((doc) => {
|
|
||||||
return doc.toClient(partial)
|
|
||||||
})
|
|
||||||
|
|
||||||
cursor.on('data', (doc) => {
|
|
||||||
projects.push(doc)
|
|
||||||
})
|
|
||||||
cursor.on('end', () => {
|
|
||||||
res.json({
|
|
||||||
total: total,
|
|
||||||
offset: skip,
|
|
||||||
count: projects.length,
|
|
||||||
items: projects
|
|
||||||
})
|
|
||||||
})
|
|
||||||
cursor.on('error', (err) => {
|
|
||||||
next(createError.InternalServerError(err.message))
|
|
||||||
})
|
|
||||||
}).catch((err) => {
|
|
||||||
next(createError.InternalServerError(err.message))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
listDashboardProjects(req, res, next) {
|
|
||||||
const Project = this.db.Project
|
|
||||||
|
|
||||||
let projects = []
|
|
||||||
let cursor = Project.find({}).select('_id name fingerprint branch').populate({
|
|
||||||
path: 'branch', select: '_id name fingerprint corporation', populate: {
|
|
||||||
path: 'corporation', select: '_id name imageId fingerprint'
|
|
||||||
}
|
|
||||||
}).cursor()
|
|
||||||
|
|
||||||
cursor.on('data', (project) => {
|
|
||||||
projects.push(project)
|
|
||||||
})
|
|
||||||
cursor.on('end', () => {
|
|
||||||
res.json({
|
|
||||||
total: projects.length,
|
|
||||||
offset: 0,
|
|
||||||
count: projects.length,
|
|
||||||
items: projects
|
|
||||||
})
|
|
||||||
})
|
|
||||||
cursor.on('error', (err) => {
|
|
||||||
next(createError.InternalServerError(err.message))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
listBrokerProjects(req, res, next) {
|
|
||||||
const brokerId = req.params._id
|
|
||||||
const Project = this.db.Project
|
|
||||||
let projects = []
|
|
||||||
let cursor = Project.find({ brokers: brokerId }).select('_id name clientData').cursor()
|
|
||||||
|
|
||||||
cursor.on('data', (project) => {
|
|
||||||
projects.push(project)
|
|
||||||
})
|
|
||||||
cursor.on('end', () => {
|
|
||||||
res.json({
|
|
||||||
total: projects.length,
|
|
||||||
offset: 0,
|
|
||||||
count: projects.length,
|
|
||||||
items: projects
|
|
||||||
})
|
|
||||||
})
|
|
||||||
cursor.on('error', (err) => {
|
|
||||||
next(createError.InternalServerError(err.message))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
createProject(req, res, next) {
|
|
||||||
const role = req.user.role
|
|
||||||
|
|
||||||
// If user's role is not Executive or Administrator, return an error
|
|
||||||
if (role !== 'executive' && role !== 'administrator') {
|
|
||||||
return next(new createError.Forbidden())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new Project template then assign it to a value in the req.body
|
|
||||||
const Project = this.db.Project
|
|
||||||
let project = new Project(req.body)
|
|
||||||
|
|
||||||
project.fingerprint = makeFingerprint(project.name)
|
|
||||||
|
|
||||||
// Save the project (with promise) - If it doesnt, catch and throw error
|
|
||||||
project.save().then((newProject) => {
|
|
||||||
res.json(newProject.toClient())
|
|
||||||
}).catch((err) => {
|
|
||||||
next(createError.InternalServerError(err.message))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
updateProject(req, res, next) {
|
|
||||||
const role = req.user.role
|
|
||||||
|
|
||||||
// If user's role is not Executive or Administrator, return an error
|
|
||||||
if (role !== 'executive' && role !== 'administrator') {
|
|
||||||
return new createError.Forbidden()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do this here because Mongoose will add it automatically otherwise
|
|
||||||
if (!req.body._id) {
|
|
||||||
return next(createError.BadRequest('No _id given in body'))
|
|
||||||
}
|
|
||||||
|
|
||||||
let Project = this.db.Project
|
|
||||||
let projectUpdates = null
|
|
||||||
|
|
||||||
try {
|
|
||||||
projectUpdates = new Project(req.body)
|
|
||||||
} catch (err) {
|
|
||||||
return next(createError.BadRequest('Invalid data'))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (projectUpdates.name) {
|
|
||||||
projectUpdates.fingerprint = makeFingerprint(projectUpdates.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
Project.findById(projectUpdates._id).then((foundProject) => {
|
|
||||||
if (!foundProject) {
|
|
||||||
return next(createError.NotFound(`Project with _id ${_id} was not found`))
|
|
||||||
}
|
|
||||||
foundProject.merge(projectUpdates)
|
|
||||||
return foundProject.save()
|
|
||||||
}).then((savedProject) => {
|
|
||||||
res.json(savedProject.toClient())
|
|
||||||
}).catch((err) => {
|
|
||||||
next(createError.InternalServerError(err.message))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
importProjectClientData(req, res, next) {
|
|
||||||
const role = req.user.role
|
|
||||||
|
|
||||||
if (role !== 'broker' && role !== 'executive' && role !== 'administrator') {
|
|
||||||
return next(new createError.Forbidden())
|
|
||||||
}
|
|
||||||
|
|
||||||
const { _id, brokerId, assetId } = req.body
|
|
||||||
|
|
||||||
if (!_id || !brokerId || !assetId) {
|
|
||||||
return next(createError.BadRequest('Must specify _id, brokerId and assetId'))
|
|
||||||
}
|
|
||||||
|
|
||||||
this.mq.request('dar-import', 'importClientData', {
|
|
||||||
projectId: _id,
|
|
||||||
brokerId: brokerId,
|
|
||||||
assetId: assetId,
|
|
||||||
passback: {
|
|
||||||
rooms: [ req.user._id ],
|
|
||||||
projectId: _id,
|
|
||||||
brokerId: brokerId,
|
|
||||||
routerName: 'projectRoutes',
|
|
||||||
funcName: 'completeImportClientData'
|
|
||||||
}
|
|
||||||
}).then((correlationId) => {
|
|
||||||
res.json({ correlationId })
|
|
||||||
}).catch((err) => {
|
|
||||||
// TODO: Should delete the asset
|
|
||||||
next(createError.InternalServerError('Unable to import uploaded file to project'))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
completeImportClientData(passback, error, data) {
|
|
||||||
if (!passback.rooms) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let obj = {
|
|
||||||
brokerId: passback.brokerId,
|
|
||||||
projectId: passback.projectId,
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
obj.problems = error.problems
|
|
||||||
obj.error = error.message
|
|
||||||
}
|
|
||||||
|
|
||||||
this.ws.notify(passback.rooms, 'clientDataImportComplete', obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
getProject(req, res, next) {
|
|
||||||
const Project = this.db.Project
|
|
||||||
const _id = req.params._id
|
|
||||||
|
|
||||||
Project.findById(_id).then((project) => {
|
|
||||||
if (!project) {
|
|
||||||
return next(createError.NotFound(`Project with _id ${_id} not found`))
|
|
||||||
}
|
|
||||||
|
|
||||||
res.json(project.toClient())
|
|
||||||
}).catch((err) => {
|
|
||||||
next(createError.InternalServerError(err.message))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
getPopulatedProject(req, res, next) {
|
|
||||||
const Project = this.db.Project
|
|
||||||
const _id = req.params._id
|
|
||||||
|
|
||||||
Project.findById(_id).then((project) => {
|
|
||||||
if (!project) {
|
|
||||||
return next(createError.NotFound(`Project with _id ${_id} not found`))
|
|
||||||
}
|
|
||||||
|
|
||||||
return project.populate({ path: 'brokers', select: '_id firstName lastName email thumbnailImageId t12 aum numHouseholds homePhone cellPhone' }).execPopulate()
|
|
||||||
}).then((project) => {
|
|
||||||
res.json(project.toClient())
|
|
||||||
}).catch((err) => {
|
|
||||||
next(createError.InternalServerError(err.message))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
getProjectBrokerClientData(req, res, next) {
|
|
||||||
const Project = this.db.Project
|
|
||||||
const _id = req.params._id
|
|
||||||
const brokerId = req.params.brokerId
|
|
||||||
|
|
||||||
Project.findById(_id).select('clientData').then((project) => {
|
|
||||||
if (!project) {
|
|
||||||
return next(createError.NotFound(`Project with _id ${_id} not found`))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!project.clientData) {
|
|
||||||
return res.json({})
|
|
||||||
}
|
|
||||||
|
|
||||||
const clientData = project.clientData.find(data => data.brokerId.toString() === brokerId)
|
|
||||||
|
|
||||||
if (clientData) {
|
|
||||||
res.json(clientData)
|
|
||||||
} else {
|
|
||||||
res.json({})
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
next(createError.InternalServerError(err.message))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
signOffProjectBrokerClientData(req, res, next) {
|
|
||||||
const Project = this.db.Project
|
|
||||||
const _id = req.params._id
|
|
||||||
const brokerId = req.params.brokerId
|
|
||||||
|
|
||||||
Project.findById(_id).then((project) => {
|
|
||||||
if (!project) {
|
|
||||||
return next(createError.NotFound(`Project with _id ${_id} not found`))
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let clientData of project.clientData) {
|
|
||||||
if (clientData.brokerId && clientData.brokerId.toString() === brokerId) {
|
|
||||||
if (clientData.submitted || clientData.numProblems !== 0 || clientData.problems.length !== 0 || clientData.error) {
|
|
||||||
return next(createError.BadRequest(`Project ${_id}, broker ${brokerId} cannot be signed off at this time`))
|
|
||||||
}
|
|
||||||
|
|
||||||
clientData.submitted = new Date()
|
|
||||||
return project.save(project)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return next(createError.NotFound(`Client data for broker ${brokerId} was not found`))
|
|
||||||
}).then((savedProject) => {
|
|
||||||
res.json({})
|
|
||||||
}).catch((error) => {
|
|
||||||
next(createError.InternalServerError(error.message))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
createProjectPackages(req, res, next) {
|
|
||||||
const role = req.user.role
|
|
||||||
|
|
||||||
if (role !== 'executive' && role !== 'administrator') {
|
|
||||||
return next(new createError.Forbidden())
|
|
||||||
}
|
|
||||||
|
|
||||||
const { projectId } = req.params
|
|
||||||
|
|
||||||
this.mq.request('dar-import', 'createPackages', {
|
|
||||||
projectId,
|
|
||||||
passback: {
|
|
||||||
rooms: [ req.user._id ], // TODO: Add a room for the specific project
|
|
||||||
projectId,
|
|
||||||
routerName: 'projectRoutes',
|
|
||||||
funcName: 'completeCreatePackageData'
|
|
||||||
}
|
|
||||||
}).then((correlationId) => {
|
|
||||||
res.json({ correlationId })
|
|
||||||
}).catch((err) => {
|
|
||||||
next(createError.InternalServerError('Unable to create package data'))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
resetProjectPackages(req, res, next) {
|
|
||||||
const role = req.user.role
|
|
||||||
|
|
||||||
if (role !== 'executive' && role !== 'administrator') {
|
|
||||||
return next(new createError.Forbidden())
|
|
||||||
}
|
|
||||||
|
|
||||||
const { projectId } = req.params
|
|
||||||
const Package = this.db.Package
|
|
||||||
const cursor = Package.find({ project: projectId }).cursor()
|
|
||||||
let totalPDFs = 0
|
|
||||||
let totalPackages = 0
|
|
||||||
|
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
cursor.on('data', (pkg) => {
|
|
||||||
pkg.remove().then((pkg) => {
|
|
||||||
if (pkg.assetId) {
|
|
||||||
totalPDFs += 1
|
|
||||||
return this.db.gridfs.remove({ _id: pkg.assetId })
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
reject(error)
|
|
||||||
})
|
|
||||||
|
|
||||||
totalPackages += 1
|
|
||||||
})
|
|
||||||
cursor.on('end', () => {
|
|
||||||
resolve()
|
|
||||||
})
|
|
||||||
cursor.on('error', (error) => {
|
|
||||||
reject(error)
|
|
||||||
})
|
|
||||||
}).then(() => {
|
|
||||||
res.json({ totalPackages, totalPDFs })
|
|
||||||
}).catch((error) => {
|
|
||||||
next(createError.InternalServerError('Unable to delete all project packages'))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
completeCreatePackageData(passback, error, data) {
|
|
||||||
if (!passback.rooms) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let obj = {
|
|
||||||
projectId: passback.projectId,
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
obj.problems = error.problems
|
|
||||||
obj.error = error.message
|
|
||||||
}
|
|
||||||
|
|
||||||
this.ws.notify(passback.rooms, 'packageGenerationComplete', obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
buildProjectPDFs(req, res, next) {
|
|
||||||
const role = req.user.role
|
|
||||||
|
|
||||||
if (role !== 'executive' && role !== 'administrator') {
|
|
||||||
return next(new createError.Forbidden())
|
|
||||||
}
|
|
||||||
|
|
||||||
const projectId = req.params.projectId
|
|
||||||
const Package = this.db.Package
|
|
||||||
let total = 0
|
|
||||||
let cursor = Package.find({ project: projectId }).cursor()
|
|
||||||
|
|
||||||
cursor.on('data', (pkg) => {
|
|
||||||
const packageId = pkg._id
|
|
||||||
this.mq.request('dar-pdf', 'createPackagePDF', {
|
|
||||||
packageId,
|
|
||||||
passback: {
|
|
||||||
rooms: [ req.user._id ], // TODO: Add a room for the specific project
|
|
||||||
packageId,
|
|
||||||
routerName: 'projectRoutes',
|
|
||||||
funcName: 'completeCreatePackagePDF'
|
|
||||||
}
|
|
||||||
}).then((correlationId) => {
|
|
||||||
res.json({ correlationId })
|
|
||||||
}).catch((err) => {
|
|
||||||
// TODO: Collect errors and return to user
|
|
||||||
})
|
|
||||||
total += 1
|
|
||||||
})
|
|
||||||
cursor.on('end', () => {
|
|
||||||
res.json({ total })
|
|
||||||
})
|
|
||||||
cursor.on('error', (err) => {
|
|
||||||
next(createError.InternalServerError(err.message))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
completeCreatePackagePDF(passback, error, data) {
|
|
||||||
if (!passback.rooms) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let obj = {
|
|
||||||
packageId: passback.packageId,
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
obj.problems = error.problems
|
|
||||||
obj.error = error.message
|
|
||||||
} else {
|
|
||||||
obj.assetId = data.assetId
|
|
||||||
}
|
|
||||||
|
|
||||||
this.ws.notify(passback.rooms, 'createPackagePDFComplete', obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteProject(req, res, next) {
|
|
||||||
const role = req.user.role
|
|
||||||
|
|
||||||
// If user's role is not Executive or Administrator, return an error
|
|
||||||
if (role !== 'executive' && role !== 'administrator') {
|
|
||||||
return new createError.Forbidden()
|
|
||||||
}
|
|
||||||
|
|
||||||
const Project = this.db.Project
|
|
||||||
const _id = req.params._id
|
|
||||||
|
|
||||||
Project.remove({ _id }).then((project) => {
|
|
||||||
if (!project) {
|
|
||||||
return next(createError.NotFound(`Project with _id ${_id} not found`))
|
|
||||||
}
|
|
||||||
|
|
||||||
res.json({})
|
|
||||||
}).catch((err) => {
|
|
||||||
next(createError.InternalServerError(err.message))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
153
server/src/api/routes/TeamRoutes.js
Normal file
153
server/src/api/routes/TeamRoutes.js
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
import passport from 'passport'
|
||||||
|
import createError from 'http-errors'
|
||||||
|
import autobind from 'autobind-decorator'
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
export class TeamRoutes {
|
||||||
|
constructor(container) {
|
||||||
|
const app = container.app
|
||||||
|
|
||||||
|
this.log = container.log
|
||||||
|
this.db = container.db
|
||||||
|
this.mq = container.mq
|
||||||
|
this.ws = container.ws
|
||||||
|
|
||||||
|
app.route('/teams')
|
||||||
|
.get(passport.authenticate('bearer', { session: false }), this.listTeams)
|
||||||
|
.post(passport.authenticate('bearer', { session: false }), this.createTeam)
|
||||||
|
.put(passport.authenticate('bearer', { session: false }), this.updateTeam)
|
||||||
|
|
||||||
|
app.route('/teams/:_id([a-f0-9]{24})')
|
||||||
|
.get(passport.authenticate('bearer', { session: false }), this.getTeam)
|
||||||
|
.delete(passport.authenticate('bearer', { session: false }), this.deleteTeam)
|
||||||
|
}
|
||||||
|
|
||||||
|
listTeams(req, res, next) {
|
||||||
|
const Team = this.db.Team
|
||||||
|
let limit = req.params.limit || 20
|
||||||
|
let skip = req.params.skip || 0
|
||||||
|
let partial = !!req.params.partial
|
||||||
|
let branch = req.params.branch
|
||||||
|
let query = {}
|
||||||
|
|
||||||
|
if (branch) {
|
||||||
|
query.branch = branch
|
||||||
|
}
|
||||||
|
|
||||||
|
Team.count({}).then((total) => {
|
||||||
|
let teams = []
|
||||||
|
let cursor = Team.find(query).limit(limit).skip(skip).cursor().map((doc) => {
|
||||||
|
return doc.toClient(partial)
|
||||||
|
})
|
||||||
|
|
||||||
|
cursor.on('data', (doc) => {
|
||||||
|
teams.push(doc)
|
||||||
|
})
|
||||||
|
cursor.on('end', () => {
|
||||||
|
res.json({
|
||||||
|
total: total,
|
||||||
|
offset: skip,
|
||||||
|
count: teams.length,
|
||||||
|
items: teams
|
||||||
|
})
|
||||||
|
})
|
||||||
|
cursor.on('error', (err) => {
|
||||||
|
next(createError.InternalServerError(err.message))
|
||||||
|
})
|
||||||
|
}).catch((err) => {
|
||||||
|
next(createError.InternalServerError(err.message))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
createTeam(req, res, next) {
|
||||||
|
const role = req.user.role
|
||||||
|
|
||||||
|
// If user's role is not Executive or Administrator, return an error
|
||||||
|
if (role !== 'executive' && role !== 'administrator') {
|
||||||
|
return next(new createError.Forbidden())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new Team template then assign it to a value in the req.body
|
||||||
|
const Team = this.db.Team
|
||||||
|
let team = new Team(req.body)
|
||||||
|
|
||||||
|
// Save the team (with promise) - If it doesnt, catch and throw error
|
||||||
|
team.save().then((newTeam) => {
|
||||||
|
res.json(newTeam.toClient())
|
||||||
|
}).catch((err) => {
|
||||||
|
next(createError.InternalServerError(err.message))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTeam(req, res, next) {
|
||||||
|
const role = req.user.role
|
||||||
|
|
||||||
|
// If user's role is not Executive or Administrator, return an error
|
||||||
|
if (role !== 'executive' && role !== 'administrator') {
|
||||||
|
return new createError.Forbidden()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do this here because Mongoose will add it automatically otherwise
|
||||||
|
if (!req.body._id) {
|
||||||
|
return next(createError.BadRequest('No _id given in body'))
|
||||||
|
}
|
||||||
|
|
||||||
|
let Team = this.db.Team
|
||||||
|
let teamUpdates = null
|
||||||
|
|
||||||
|
try {
|
||||||
|
teamUpdates = new Team(req.body)
|
||||||
|
} catch (err) {
|
||||||
|
return next(createError.BadRequest('Invalid data'))
|
||||||
|
}
|
||||||
|
|
||||||
|
Team.findById(teamUpdates._id).then((foundTeam) => {
|
||||||
|
if (!foundTeam) {
|
||||||
|
return next(createError.NotFound(`Team with _id ${_id} was not found`))
|
||||||
|
}
|
||||||
|
foundTeam.merge(teamUpdates)
|
||||||
|
return foundTeam.save()
|
||||||
|
}).then((savedTeam) => {
|
||||||
|
res.json(savedTeam.toClient())
|
||||||
|
}).catch((err) => {
|
||||||
|
next(createError.InternalServerError(err.message))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
getTeam(req, res, next) {
|
||||||
|
const Team = this.db.Team
|
||||||
|
const _id = req.params._id
|
||||||
|
|
||||||
|
Team.findById(_id).then((team) => {
|
||||||
|
if (!team) {
|
||||||
|
return next(createError.NotFound(`Team with _id ${_id} not found`))
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json(team.toClient())
|
||||||
|
}).catch((err) => {
|
||||||
|
next(createError.InternalServerError(err.message))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteTeam(req, res, next) {
|
||||||
|
const role = req.user.role
|
||||||
|
|
||||||
|
// If user's role is not Executive or Administrator, return an error
|
||||||
|
if (role !== 'executive' && role !== 'administrator') {
|
||||||
|
return new createError.Forbidden()
|
||||||
|
}
|
||||||
|
|
||||||
|
const Team = this.db.Team
|
||||||
|
const _id = req.params._id
|
||||||
|
|
||||||
|
Team.remove({ _id }).then((team) => {
|
||||||
|
if (!project) {
|
||||||
|
return next(createError.NotFound(`Team with _id ${_id} not found`))
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json({})
|
||||||
|
}).catch((err) => {
|
||||||
|
next(createError.InternalServerError(err.message))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
153
server/src/api/routes/WorkItemRoutes.js
Normal file
153
server/src/api/routes/WorkItemRoutes.js
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
import passport from 'passport'
|
||||||
|
import createError from 'http-errors'
|
||||||
|
import autobind from 'autobind-decorator'
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
export class WorkItemRoutes {
|
||||||
|
constructor(container) {
|
||||||
|
const app = container.app
|
||||||
|
|
||||||
|
this.log = container.log
|
||||||
|
this.db = container.db
|
||||||
|
this.mq = container.mq
|
||||||
|
this.ws = container.ws
|
||||||
|
|
||||||
|
app.route('/workitems')
|
||||||
|
.get(passport.authenticate('bearer', { session: false }), this.listWorkItems)
|
||||||
|
.post(passport.authenticate('bearer', { session: false }), this.createWorkItem)
|
||||||
|
.put(passport.authenticate('bearer', { session: false }), this.updateWorkItem)
|
||||||
|
|
||||||
|
app.route('/workitems/:_id([a-f0-9]{24})')
|
||||||
|
.get(passport.authenticate('bearer', { session: false }), this.getWorkItem)
|
||||||
|
.delete(passport.authenticate('bearer', { session: false }), this.deleteWorkItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
listWorkItems(req, res, next) {
|
||||||
|
const WorkItem = this.db.WorkItem
|
||||||
|
let limit = req.params.limit || 20
|
||||||
|
let skip = req.params.skip || 0
|
||||||
|
let partial = !!req.params.partial
|
||||||
|
let branch = req.params.branch
|
||||||
|
let query = {}
|
||||||
|
|
||||||
|
if (branch) {
|
||||||
|
query.branch = branch
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkItem.count({}).then((total) => {
|
||||||
|
let workItems = []
|
||||||
|
let cursor = WorkItem.find(query).limit(limit).skip(skip).cursor().map((doc) => {
|
||||||
|
return doc.toClient(partial)
|
||||||
|
})
|
||||||
|
|
||||||
|
cursor.on('data', (doc) => {
|
||||||
|
workItems.push(doc)
|
||||||
|
})
|
||||||
|
cursor.on('end', () => {
|
||||||
|
res.json({
|
||||||
|
total: total,
|
||||||
|
offset: skip,
|
||||||
|
count: workItems.length,
|
||||||
|
items: workItems
|
||||||
|
})
|
||||||
|
})
|
||||||
|
cursor.on('error', (err) => {
|
||||||
|
next(createError.InternalServerError(err.message))
|
||||||
|
})
|
||||||
|
}).catch((err) => {
|
||||||
|
next(createError.InternalServerError(err.message))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
createWorkItem(req, res, next) {
|
||||||
|
const role = req.user.role
|
||||||
|
|
||||||
|
// If user's role is not Executive or Administrator, return an error
|
||||||
|
if (role !== 'executive' && role !== 'administrator') {
|
||||||
|
return next(new createError.Forbidden())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new WorkItem template then assign it to a value in the req.body
|
||||||
|
const WorkItem = this.db.WorkItem
|
||||||
|
let workItem = new WorkItem(req.body)
|
||||||
|
|
||||||
|
// Save the workItem (with promise) - If it doesnt, catch and throw error
|
||||||
|
workItem.save().then((newWorkItem) => {
|
||||||
|
res.json(newWorkItem.toClient())
|
||||||
|
}).catch((err) => {
|
||||||
|
next(createError.InternalServerError(err.message))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
updateWorkItem(req, res, next) {
|
||||||
|
const role = req.user.role
|
||||||
|
|
||||||
|
// If user's role is not Executive or Administrator, return an error
|
||||||
|
if (role !== 'executive' && role !== 'administrator') {
|
||||||
|
return new createError.Forbidden()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do this here because Mongoose will add it automatically otherwise
|
||||||
|
if (!req.body._id) {
|
||||||
|
return next(createError.BadRequest('No _id given in body'))
|
||||||
|
}
|
||||||
|
|
||||||
|
let WorkItem = this.db.WorkItem
|
||||||
|
let workItemUpdates = null
|
||||||
|
|
||||||
|
try {
|
||||||
|
workItemUpdates = new WorkItem(req.body)
|
||||||
|
} catch (err) {
|
||||||
|
return next(createError.BadRequest('Invalid data'))
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkItem.findById(workItemUpdates._id).then((foundWorkItem) => {
|
||||||
|
if (!foundWorkItem) {
|
||||||
|
return next(createError.NotFound(`WorkItem with _id ${_id} was not found`))
|
||||||
|
}
|
||||||
|
foundWorkItem.merge(workItemUpdates)
|
||||||
|
return foundWorkItem.save()
|
||||||
|
}).then((savedWorkItem) => {
|
||||||
|
res.json(savedWorkItem.toClient())
|
||||||
|
}).catch((err) => {
|
||||||
|
next(createError.InternalServerError(err.message))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
getWorkItem(req, res, next) {
|
||||||
|
const WorkItem = this.db.WorkItem
|
||||||
|
const _id = req.params._id
|
||||||
|
|
||||||
|
WorkItem.findById(_id).then((workItem) => {
|
||||||
|
if (!workItem) {
|
||||||
|
return next(createError.NotFound(`WorkItem with _id ${_id} not found`))
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json(workItem.toClient())
|
||||||
|
}).catch((err) => {
|
||||||
|
next(createError.InternalServerError(err.message))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteWorkItem(req, res, next) {
|
||||||
|
const role = req.user.role
|
||||||
|
|
||||||
|
// If user's role is not Executive or Administrator, return an error
|
||||||
|
if (role !== 'executive' && role !== 'administrator') {
|
||||||
|
return new createError.Forbidden()
|
||||||
|
}
|
||||||
|
|
||||||
|
const WorkItem = this.db.WorkItem
|
||||||
|
const _id = req.params._id
|
||||||
|
|
||||||
|
WorkItem.remove({ _id }).then((workItem) => {
|
||||||
|
if (!workItem) {
|
||||||
|
return next(createError.NotFound(`WorkItem with _id ${_id} not found`))
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json({})
|
||||||
|
}).catch((err) => {
|
||||||
|
next(createError.InternalServerError(err.message))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
export { AuthRoutes } from './AuthRoutes'
|
export { AuthRoutes } from './AuthRoutes'
|
||||||
export { AssetRoutes } from './AssetRoutes'
|
export { AssetRoutes } from './AssetRoutes'
|
||||||
export { UserRoutes } from './UserRoutes'
|
export { UserRoutes } from './UserRoutes'
|
||||||
|
export { WorkItemRoutes } from './WorkItemRoutes'
|
||||||
|
export { ActivityRoutes } from './ActivityRoutes'
|
||||||
|
export { TeamRoutes } from './TeamRoutes'
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ export class DB {
|
|||||||
|
|
||||||
this.User = connection.model('User', Schemas.userSchema)
|
this.User = connection.model('User', Schemas.userSchema)
|
||||||
this.WorkItem = connection.model('WorkItem', Schemas.workItemSchema)
|
this.WorkItem = connection.model('WorkItem', Schemas.workItemSchema)
|
||||||
|
this.Activity = connection.model('Activity', Schemas.activitySchema)
|
||||||
|
this.Team = connection.model('Team', Schemas.teamSchema)
|
||||||
|
|
||||||
return Promise.resolve(this)
|
return Promise.resolve(this)
|
||||||
})
|
})
|
||||||
|
|||||||
25
server/src/database/schemas/activity.js
Normal file
25
server/src/database/schemas/activity.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { Schema } from 'mongoose'
|
||||||
|
|
||||||
|
export let activitySchema = new Schema({
|
||||||
|
_id: { type: Schema.Types.ObjectId, required: true, auto: true },
|
||||||
|
resolution: String,
|
||||||
|
workItem: { type: Schema.Types.ObjectId, required: true },
|
||||||
|
status: { type: String, required: true, enum: {
|
||||||
|
values: [ 'planned', 'open', 'onHold', 'closed'],
|
||||||
|
message: 'enum validator failed for path `{PATH}` with value `{VALUE}`'
|
||||||
|
}},
|
||||||
|
notes: String,
|
||||||
|
when: Date,
|
||||||
|
loc: {
|
||||||
|
type: { type: String },
|
||||||
|
coordinates: [Number],
|
||||||
|
},
|
||||||
|
address: String,
|
||||||
|
fromStreetNumber: Number,
|
||||||
|
toStreetNumber: Number,
|
||||||
|
photos: [ Schema.Types.ObjectId ],
|
||||||
|
}, { timestamps: true, id: false })
|
||||||
|
|
||||||
|
activitySchema.methods.toClient = function() {
|
||||||
|
return this.toObject()
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
export { workItemSchema } from './workItem'
|
export { workItemSchema } from './workItem'
|
||||||
export { userSchema } from './user'
|
export { userSchema } from './user'
|
||||||
export { teamSchema } from './team'
|
export { teamSchema } from './team'
|
||||||
|
export { activitySchema } from './activity'
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import { Schema } from 'mongoose'
|
import { Schema } from 'mongoose'
|
||||||
|
|
||||||
export let team = new Schema({
|
export let teamSchema = new Schema({
|
||||||
name: { type: String },
|
name: { type: String },
|
||||||
members: { type: Schema.Types.ObjectId, required: true },
|
|
||||||
}, { timestamps: true, id: false })
|
}, { timestamps: true, id: false })
|
||||||
|
|
||||||
|
teamSchema.methods.toClient = function() {
|
||||||
|
return this.toObject()
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ export let userSchema = new Schema({
|
|||||||
},
|
},
|
||||||
email: { type: String, match: regExpPattern.email, required: true, index: true, unique: true },
|
email: { type: String, match: regExpPattern.email, required: true, index: true, unique: true },
|
||||||
newEmail: { type: String, match: regExpPattern.email },
|
newEmail: { type: String, match: regExpPattern.email },
|
||||||
imageId: { type: Schema.Types.ObjectId },
|
|
||||||
thumbnailImageId: { type: Schema.Types.ObjectId },
|
thumbnailImageId: { type: Schema.Types.ObjectId },
|
||||||
emailToken: {
|
emailToken: {
|
||||||
type: {
|
type: {
|
||||||
@@ -32,6 +31,7 @@ export let userSchema = new Schema({
|
|||||||
firstName: { type: String, required: true },
|
firstName: { type: String, required: true },
|
||||||
lastName: { type: String, required: true },
|
lastName: { type: String, required: true },
|
||||||
administrator: { type: Boolean, required: true },
|
administrator: { type: Boolean, required: true },
|
||||||
|
team: Schema.Types.ObjectId,
|
||||||
}, { timestamps: true, id: false })
|
}, { timestamps: true, id: false })
|
||||||
|
|
||||||
userSchema.methods.toClient = function(authUser) {
|
userSchema.methods.toClient = function(authUser) {
|
||||||
@@ -47,7 +47,8 @@ userSchema.methods.toClient = function(authUser) {
|
|||||||
thumbnailImageId: this.thumbnailImageId,
|
thumbnailImageId: this.thumbnailImageId,
|
||||||
firstName: this.firstName,
|
firstName: this.firstName,
|
||||||
lastName: this.lastName,
|
lastName: this.lastName,
|
||||||
administrator: this.administrator
|
administrator: this.administrator,
|
||||||
|
team: this.team
|
||||||
}
|
}
|
||||||
|
|
||||||
return user
|
return user
|
||||||
|
|||||||
@@ -7,11 +7,16 @@ export let workItemSchema = new Schema({
|
|||||||
values: [ 'order', 'inspection', 'complaint'],
|
values: [ 'order', 'inspection', 'complaint'],
|
||||||
message: 'enum validator failed for path `{PATH}` with value `{VALUE}`'
|
message: 'enum validator failed for path `{PATH}` with value `{VALUE}`'
|
||||||
}},
|
}},
|
||||||
|
number: Number,
|
||||||
|
loc: {
|
||||||
|
type: { type: String },
|
||||||
|
coordinates: [Number],
|
||||||
|
},
|
||||||
|
address: String,
|
||||||
|
photos: [ Schema.Types.ObjectId ],
|
||||||
|
details: String,
|
||||||
}, { timestamps: true, id: false })
|
}, { timestamps: true, id: false })
|
||||||
|
|
||||||
workItemSchema.methods.toClient = function() {
|
workItemSchema.methods.toClient = function() {
|
||||||
return {
|
return this.toObject()
|
||||||
_id: this._id,
|
|
||||||
workItemType: this.workItemType
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user