Skip to content
This repository has been archived by the owner on Apr 4, 2024. It is now read-only.

Commit

Permalink
Merge pull request #5 from digicatapult/feature/post-project-with-client
Browse files Browse the repository at this point in the history
post project route accepts client id or client creation, one of schem…
  • Loading branch information
darrylmorton-digicatapult authored May 20, 2022
2 parents f988872 + efe9d2d commit 85bae37
Show file tree
Hide file tree
Showing 15 changed files with 375 additions and 143 deletions.
55 changes: 54 additions & 1 deletion app/api-v1/api-doc.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ const apiDoc = {
},
required: ['id', 'clientId', 'name', 'description'],
},
PostAndPutProject: {
PostAndPutProjectWithClientId: {
description: 'Schema for creating/updating a project',
type: 'object',
properties: {
Expand Down Expand Up @@ -170,6 +170,59 @@ const apiDoc = {
},
required: ['clientId', 'name', 'description'],
},
PostAndPutProjectWithClient: {
description: 'Schema for creating/updating a project',
type: 'object',
properties: {
firstName: {
description: 'First name of the client',
type: 'string',
},
lastName: {
description: 'Last name of the client',
type: 'string',
},
company: {
description: 'Company of the client',
type: 'string',
},
role: {
description: 'Role of the client',
type: 'string',
},
name: {
description: 'Name of the project',
type: 'string',
},
description: {
description: 'Description of the project',
type: 'string',
},
startDate: {
description: 'Start date of the project',
type: 'string',
format: 'date-time',
nullable: true,
},
endDate: {
description: 'End date of the project',
type: 'string',
format: 'date-time',
nullable: true,
},
budget: {
description: 'Budget of the project',
type: 'number',
nullable: true,
},
documentUrl: {
description: 'Document url of the project',
type: 'string',
nullable: true,
},
},
required: ['firstName', 'lastName', 'company', 'role', 'name', 'description'],
},
},
},
paths: {},
Expand Down
5 changes: 4 additions & 1 deletion app/api-v1/routes/profiler/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ module.exports = function (apiService) {
content: {
'application/json': {
schema: {
$ref: '#/components/schemas/PostAndPutProject',
oneOf: [
{ $ref: '#/components/schemas/PostAndPutProjectWithClientId' },
{ $ref: '#/components/schemas/PostAndPutProjectWithClient' },
],
},
},
},
Expand Down
5 changes: 4 additions & 1 deletion app/api-v1/routes/profiler/project/{id}.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,10 @@ module.exports = function (apiService) {
content: {
'application/json': {
schema: {
$ref: '#/components/schemas/PostAndPutProject',
oneOf: [
{ $ref: '#/components/schemas/PostAndPutProjectWithClientId' },
{ $ref: '#/components/schemas/PostAndPutProjectWithClient' },
],
},
},
},
Expand Down
52 changes: 43 additions & 9 deletions app/api-v1/services/apiService.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const {
findClientByIdDb,
updateClientDb,
removeClientDb,
findProjectByNameAndWhereNotIdDb,
} = require('../../db')

async function getClients() {
Expand Down Expand Up @@ -78,25 +79,58 @@ async function postProject(reqBody) {
const findResult = await findProjectByNameDb(reqBody.name)

if (findResult.length === 0) {
const result = await addProjectDb(reqBody)
if (reqBody.clientId) {
const { statusCode: clientStatusCode } = await getClientById(reqBody.clientId)

return { statusCode: 201, result: result[0] }
if (clientStatusCode === 200) {
const result = await addProjectDb(reqBody)

return { statusCode: 201, result: result[0] }
} else {
return { statusCode: clientStatusCode, result: {} }
}
} else {
const { statusCode: clientStatusCode, result: clientResult } = await postClient(reqBody)

if (clientStatusCode === 201) {
const result = await addProjectDb({ ...reqBody, clientId: clientResult.id })

return { statusCode: 201, result: result[0] }
}
}
} else {
return { statusCode: 409, result: {} }
}
}

async function putProject(id, reqBody) {
const findResult = await findProjectByIdDb(id)
// lookup existing project by id
const findProjectByIdResult = await findProjectByIdDb(id)

if (findResult.length === 0) {
// exists?
if (findProjectByIdResult.length === 0) {
return { statusCode: 404, result: {} }
} else if (findResult[0].name !== reqBody.name) {
const result = await updateProjectDb(id, reqBody)

return { statusCode: 200, result: result[0] }
} else {
return { statusCode: 409, result: {} }
// lookup all projects by name in case of clash, but exclude current project id as not a clash if name is unchanged
const findProjectByNameAndWhereNotIdResult = await findProjectByNameAndWhereNotIdDb(reqBody.name, id)

if (findProjectByNameAndWhereNotIdResult.length === 0) {
if (reqBody.clientId) {
const result = await updateProjectDb(id, reqBody)

return { statusCode: 200, result: result[0] }
} else {
const { statusCode: clientStatusCode, result: clientResult } = await postClient(reqBody)

if (clientStatusCode === 201) {
const result = await updateProjectDb(id, { ...reqBody, clientId: clientResult.id })

return { statusCode: 200, result: result[0] }
}
}
} else {
return { statusCode: 409, result: {} }
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const PUT_PROJECT_RESPONSES = {
},
400: apiDocResponses['400'],
404: apiDocResponses['404'],
409: apiDocResponses['409'],
default: apiDocResponses.default,
}

Expand Down
5 changes: 5 additions & 0 deletions app/db.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ async function findProjectByNameDb(name) {
return client('projects').select('name').where({ name })
}

async function findProjectByNameAndWhereNotIdDb(name, id) {
return client('projects').select('name').where({ name }).andWhereNot({ id })
}

async function findProjectByIdDb(id) {
return client('projects')
.select([
Expand Down Expand Up @@ -140,6 +144,7 @@ module.exports = {
removeClientDb,
findProjectsDb,
findProjectByNameDb,
findProjectByNameAndWhereNotIdDb,
addProjectDb,
findProjectByIdDb,
removeProjectDb,
Expand Down
2 changes: 1 addition & 1 deletion app/env.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const vars = envalid.cleanEnv(
process.env,
{
SERVICE_TYPE: envalid.str({ default: 'adcp-profiler-service'.toUpperCase().replace(/-/g, '_') }),
PORT: envalid.port({ default: 80, devDefault: 3000 }),
PORT: envalid.port({ default: 80, devDefault: 3001 }),
API_VERSION: envalid.str({ default: version }),
API_MAJOR_VERSION: envalid.str({ default: 'v1' }),
LOG_LEVEL: envalid.str({ default: 'info', devDefault: 'debug' }),
Expand Down
4 changes: 2 additions & 2 deletions helm/adcp-profiler-service/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
apiVersion: v2
name: adcp-profiler-service
appVersion: '0.0.4'
appVersion: '0.0.5'
description: A Helm chart for adcp-profiler-service
version: '0.0.4'
version: '0.0.5'
type: application
maintainers:
- name: digicatapult
Expand Down
2 changes: 1 addition & 1 deletion helm/adcp-profiler-service/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ config:
image:
repository: ghcr.io/digicatapult/adcp-profiler-service
pullPolicy: IfNotPresent
tag: 'v0.0.4'
tag: 'v0.0.5'
pullSecrets: ['ghcr-digicatapult']
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@digicatapult/adcp-profiler-service",
"version": "0.0.4",
"version": "0.0.5",
"description": "Insert repo description",
"main": "app/index.js",
"scripts": {
Expand Down
43 changes: 40 additions & 3 deletions test/helper/appHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,23 @@ const createDefaultClient = () => {
})
}

const createDefaultProjectWithClient = (project, client) => {
const projectObj = createProject(project)
const clientObj = createDefaultClient(client)

return {
...projectObj,
...clientObj,
}
}

const assertUuidV4 = (id) => {
expect(uuidValidate(id) && uuidVersion(id) === 4).to.be.true
}

const assertClientParams = (actualResult, expectedResult) => {
assertUuidV4(actualResult.id)

expect(actualResult.firstName).to.equal(expectedResult.firstName)
expect(actualResult.lastName).to.equal(expectedResult.lastName)
expect(actualResult.company).to.equal(expectedResult.company)
Expand All @@ -53,20 +64,43 @@ const assertGetClients = (actualResults, expectedResults) => {

const assertPostProjectRequiredParams = (actualResult, expectedResult) => {
assertUuidV4(actualResult.id)

expect(actualResult.clientId).to.equal(expectedResult.clientId)
expect(actualResult.name).to.equal(expectedResult.name)
expect(actualResult.description).to.equal(expectedResult.description)
}

const assertPostProjectParams = (actualResult, expectedResult) => {
assertPostProjectRequiredParams(actualResult, expectedResult)

const assertPostProjectOptionalParams = (actualResult, expectedResult) => {
expect(actualResult.startDate).to.equal(expectedResult.startDate)
expect(actualResult.endDate).to.equal(expectedResult.endDate)
expect(actualResult.budget).to.equal(expectedResult.budget)
expect(actualResult.documentUrl).to.equal(expectedResult.documentUrl)
}

const assertPostProjectParams = (actualResult, expectedResult) => {
assertPostProjectRequiredParams(actualResult, expectedResult)

assertPostProjectOptionalParams(actualResult, expectedResult)
}

const assertPostProjectWithUnknownClientIdRequiredParams = (actualResult, expectedResult) => {
assertUuidV4(actualResult.id)
assertUuidV4(actualResult.clientId)

expect(actualResult.name).to.equal(expectedResult.name)
expect(actualResult.description).to.equal(expectedResult.description)
}

const assertPostProjectWithUnknownClientIdParams = (actualResult, expectedResult) => {
assertUuidV4(actualResult.id)
assertUuidV4(actualResult.clientId)

expect(actualResult.name).to.equal(expectedResult.name)
expect(actualResult.description).to.equal(expectedResult.description)

assertPostProjectOptionalParams(actualResult, expectedResult)
}

const assertGetProjects = (actualResults, expectedResults) => {
expect(actualResults.length).to.equal(expectedResults.length)

Expand All @@ -82,8 +116,11 @@ module.exports = {
assertGetClients,
createProject,
createDefaultProject,
createDefaultProjectWithClient,
assertUuidV4,
assertPostProjectParams,
assertPostProjectRequiredParams,
assertPostProjectWithUnknownClientIdRequiredParams,
assertPostProjectWithUnknownClientIdParams,
assertGetProjects,
}
2 changes: 1 addition & 1 deletion test/integration/clientRoutes.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const {
putClientRoute,
deleteClientRoute,
} = require('../helper/clientRouteHelper')
const { cleanupAll, cleanup } = require('../helper/seeds/project')
const { cleanupAll, cleanup } = require('../seeds/project')

describe('Client routes', function () {
let app
Expand Down
Loading

0 comments on commit 85bae37

Please sign in to comment.