From 4529c2260c22705415f4febeeaa337932a9f239c Mon Sep 17 00:00:00 2001 From: Michael Taylor Date: Thu, 20 Jan 2022 19:09:23 -0500 Subject: [PATCH] feat: add datalayer simulatorv2 --- .../Projects API.postman_collection.json | 635 ++++++++---------- docs/postman/createProjects.csv | 10 + docs/postman/updateProjects.csv | 4 + package-lock.json | 88 +++ package.json | 1 + src/controllers/organization.controller.js | 10 +- src/controllers/project.controller.js | 39 +- src/controllers/staging.controller.js | 132 ++++ src/controllers/units.controller.js | 11 + src/controllers/vintage.controller.js | 24 +- src/fullnode/dataLayerService.js | 162 +++++ src/fullnode/datalayer.js | 47 -- src/fullnode/index.js | 1 + src/fullnode/persistance.js | 72 ++ src/fullnode/simulatorV2.js | 54 ++ src/models/meta/meta.model.js | 3 + src/models/meta/meta.modeltypes.cjs | 4 +- .../organizations/organizations.model.js | 35 +- src/models/vintages/vintages.stub.json | 30 +- src/routes/v1/resources/organization.js | 4 + src/routes/v1/resources/staging.js | 2 +- src/utils/csv-utils.js | 10 +- src/utils/data-assertions.js | 11 + src/validations/units.validations.js | 2 +- 24 files changed, 935 insertions(+), 456 deletions(-) create mode 100644 docs/postman/createProjects.csv create mode 100644 docs/postman/updateProjects.csv create mode 100644 src/fullnode/dataLayerService.js delete mode 100644 src/fullnode/datalayer.js create mode 100644 src/fullnode/persistance.js create mode 100644 src/fullnode/simulatorV2.js diff --git a/docs/postman/Projects API.postman_collection.json b/docs/postman/Projects API.postman_collection.json index d4b58c6a..03089c98 100644 --- a/docs/postman/Projects API.postman_collection.json +++ b/docs/postman/Projects API.postman_collection.json @@ -16,217 +16,188 @@ "path": ["projects"] } }, - "response": [ - { - "name": "GET Projects", - "originalRequest": { - "method": "GET", - "header": [], - "url": { - "raw": "{{api_url_v1}}/projects", - "host": ["{{api_url_v1}}"], - "path": ["projects"] - } - }, - "_postman_previewlanguage": null, - "header": null, - "cookie": [], - "body": null - }, - { - "name": "GET Projects with all projectsGetQuerySchema params", - "originalRequest": { - "method": "GET", - "header": [], - "url": { - "raw": "{{api_url_v1}}/projects?page=1&limit=10&search=skinte&columns=all&warehouseProjectId=da494c65-17ec-4694-85df-e44de2c77cf5", - "host": ["{{api_url_v1}}"], - "path": ["projects"], - "query": [ - { - "key": "page", - "value": "1" - }, - { - "key": "limit", - "value": "10" - }, - { - "key": "search", - "value": "skinte" - }, - { - "key": "columns", - "value": "all" - }, - { - "key": "warehouseProjectId", - "value": "da494c65-17ec-4694-85df-e44de2c77cf5" - } - ] + "response": [] + }, + { + "name": "GET Projects with all projectsGetQuerySchema params", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{api_url_v1}}/projects?page=1&limit=10&search=skinte&columns=all&warehouseProjectId=da494c65-17ec-4694-85df-e44de2c77cf5", + "host": ["{{api_url_v1}}"], + "path": ["projects"], + "query": [ + { + "key": "page", + "value": "1" + }, + { + "key": "limit", + "value": "10" + }, + { + "key": "search", + "value": "skinte" + }, + { + "key": "columns", + "value": "all" + }, + { + "key": "warehouseProjectId", + "value": "da494c65-17ec-4694-85df-e44de2c77cf5" } - }, - "_postman_previewlanguage": null, - "header": null, - "cookie": [], - "body": null - }, - { - "name": "GET Projects with displayed columns (with paging)", - "originalRequest": { - "method": "GET", - "header": [], - "url": { - "raw": "{{api_url_v1}}/projects?page=1&limit=5&columns=organization&columns=warehouseProjectId&columns=currentRegistry&columns=registryOfOrigin&columns=originProjectId&columns=program&columns=projectName", - "host": ["{{api_url_v1}}"], - "path": ["projects"], - "query": [ - { - "key": "page", - "value": "1" - }, - { - "key": "limit", - "value": "5" - }, - { - "key": "columns", - "value": "organization" - }, - { - "key": "columns", - "value": "warehouseProjectId" - }, - { - "key": "columns", - "value": "currentRegistry" - }, - { - "key": "columns", - "value": "registryOfOrigin" - }, - { - "key": "columns", - "value": "originProjectId" - }, - { - "key": "columns", - "value": "program" - }, - { - "key": "columns", - "value": "projectName" - } - ] + ] + } + }, + "response": [] + }, + { + "name": "GET Projects with displayed columns (with paging)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{api_url_v1}}/projects?page=1&limit=5&columns=organization&columns=warehouseProjectId&columns=currentRegistry&columns=registryOfOrigin&columns=originProjectId&columns=program&columns=projectName", + "host": ["{{api_url_v1}}"], + "path": ["projects"], + "query": [ + { + "key": "page", + "value": "1" + }, + { + "key": "limit", + "value": "5" + }, + { + "key": "columns", + "value": "organization" + }, + { + "key": "columns", + "value": "warehouseProjectId" + }, + { + "key": "columns", + "value": "currentRegistry" + }, + { + "key": "columns", + "value": "registryOfOrigin" + }, + { + "key": "columns", + "value": "originProjectId" + }, + { + "key": "columns", + "value": "program" + }, + { + "key": "columns", + "value": "projectName" } - }, - "_postman_previewlanguage": null, - "header": null, - "cookie": [], - "body": null - }, - { - "name": "GET Projects with displayed columns (without paging)", - "originalRequest": { - "method": "GET", - "header": [], - "url": { - "raw": "{{api_url_v1}}/projects?columns=organization&columns=warehouseProjectId&columns=currentRegistry&columns=registryOfOrigin&columns=originProjectId&columns=program&columns=projectName", - "host": ["{{api_url_v1}}"], - "path": ["projects"], - "query": [ - { - "key": "columns", - "value": "organization" - }, - { - "key": "columns", - "value": "warehouseProjectId" - }, - { - "key": "columns", - "value": "currentRegistry" - }, - { - "key": "columns", - "value": "registryOfOrigin" - }, - { - "key": "columns", - "value": "originProjectId" - }, - { - "key": "columns", - "value": "program" - }, - { - "key": "columns", - "value": "projectName" - } - ] + ] + } + }, + "response": [] + }, + { + "name": "GET Projects with displayed columns (without paging)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{api_url_v1}}/projects?columns=organization&columns=warehouseProjectId&columns=currentRegistry&columns=registryOfOrigin&columns=originProjectId&columns=program&columns=projectName", + "host": ["{{api_url_v1}}"], + "path": ["projects"], + "query": [ + { + "key": "columns", + "value": "organization" + }, + { + "key": "columns", + "value": "warehouseProjectId" + }, + { + "key": "columns", + "value": "currentRegistry" + }, + { + "key": "columns", + "value": "registryOfOrigin" + }, + { + "key": "columns", + "value": "originProjectId" + }, + { + "key": "columns", + "value": "program" + }, + { + "key": "columns", + "value": "projectName" } - }, - "_postman_previewlanguage": null, - "header": null, - "cookie": [], - "body": null - }, - { - "name": "GET Projects with specific columns", - "originalRequest": { - "method": "GET", - "header": [], - "url": { - "raw": "{{api_url_v1}}/projects?page=1&limit=10&columns=warehouseProjectId&columns=projectId&columns=projectName&columns=projectType&columns=projectStatus", - "host": ["{{api_url_v1}}"], - "path": ["projects"], - "query": [ - { - "key": "page", - "value": "1" - }, - { - "key": "limit", - "value": "10" - }, - { - "key": "columns", - "value": "warehouseProjectId" - }, - { - "key": "columns", - "value": "projectId" - }, - { - "key": "columns", - "value": "projectName" - }, - { - "key": "columns", - "value": "projectType" - }, - { - "key": "columns", - "value": "projectStatus" - } - ] + ] + } + }, + "response": [] + }, + { + "name": "GET Projects with specific columns", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{api_url_v1}}/projects?page=1&limit=10&columns=warehouseProjectId&columns=projectId&columns=projectName&columns=projectType&columns=projectStatus", + "host": ["{{api_url_v1}}"], + "path": ["projects"], + "query": [ + { + "key": "page", + "value": "1" + }, + { + "key": "limit", + "value": "10" + }, + { + "key": "columns", + "value": "warehouseProjectId" + }, + { + "key": "columns", + "value": "projectId" + }, + { + "key": "columns", + "value": "projectName" + }, + { + "key": "columns", + "value": "projectType" + }, + { + "key": "columns", + "value": "projectStatus" } - }, - "_postman_previewlanguage": null, - "header": null, - "cookie": [], - "body": null + ] } - ] + }, + "response": [] }, { - "name": "POST Projects", + "name": "POST Projects with projectsPostSchema", "request": { "method": "POST", "header": [], "body": { "mode": "raw", - "raw": "{\r\n \"originProjectId\": \"c5067a60-e329-4510-991c-b302fd00ec8d\",\r\n \"projectId\": \"11954678-f7a5-47d2-94f8-f4f3138a529c\",\r\n \"program\": \"Eimbee\",\r\n \"projectName\": \"Zoomcast\",\r\n \"projectLink\": \"http://dailymotion.com/ligula/suspendisse/ornare/consequat/lectus/in.jpg?aliquam=consequat&lacus=nulla&morbi=nisl&quis=nunc&tortor=nisl&id=duis&nulla=bibendum&ultrices=felis&aliquet=sed&maecenas=interdum&leo=venenatis&odio=turpis&condimentum=enim&id=blandit&luctus=mi&nec=in&molestie=porttitor&sed=pede&justo=justo&pellentesque=eu&viverra=massa&pede=donec&ac=dapibus&diam=duis&cras=at&pellentesque=velit&volutpat=eu&dui=est&maecenas=congue&tristique=elementum&est=in&et=hac&tempus=habitasse&semper=platea&est=dictumst&quam=morbi&pharetra=vestibulum&magna=velit&ac=id&consequat=pretium&metus=iaculis&sapien=diam&ut=erat&nunc=fermentum&vestibulum=justo&ante=nec&ipsum=condimentum\",\r\n \"projectDeveloper\": \"Cogibox\",\r\n \"projectType\": \"Topicshots\",\r\n \"coveredByNDC\": 0,\r\n \"NDCLinkage\": \"Shuffletag\",\r\n \"projectStatus\": \"I know many children ask for a pony, but I wanted a bicycle with rockets strapped to it.\",\r\n \"projectStatusDate\": \"2022-01-19\",\r\n \"unitMetric\": \"Fuscia\",\r\n \"methodology\": \"Quatz\",\r\n \"methodologyVersion\": 43,\r\n \"validationApproach\": \"He waited for the stop sign to turn to a go sign.\",\r\n \"validationDate\": \"2022-01-19\",\r\n \"projectTag\": \"Kaymbo\",\r\n \"estimatedAnnualAverageEmissionReduction\": \"60\"\r\n}", + "raw": "{\r\n \"originProjectId\": \"c5067a60-e329-4510-991c-b302fd00ec8d\",\r\n \"projectId\": \"c9d147e2-bc07-4e68-a76d-43424fa8cd4e\",\r\n \"program\": \"Eimbee\",\r\n \"projectName\": \"Zoomcast\",\r\n \"projectLink\": \"http://dailymotion.com/ligula/suspendisse/ornare/consequat/lectus/in.jpg?aliquam=consequat&lacus=nulla&morbi=nisl&quis=nunc&tortor=nisl&id=duis&nulla=bibendum&ultrices=felis&aliquet=sed&maecenas=interdum&leo=venenatis&odio=turpis&condimentum=enim&id=blandit&luctus=mi&nec=in&molestie=porttitor&sed=pede&justo=justo&pellentesque=eu&viverra=massa&pede=donec&ac=dapibus&diam=duis&cras=at&pellentesque=velit&volutpat=eu&dui=est&maecenas=congue&tristique=elementum&est=in&et=hac&tempus=habitasse&semper=platea&est=dictumst&quam=morbi&pharetra=vestibulum&magna=velit&ac=id&consequat=pretium&metus=iaculis&sapien=diam&ut=erat&nunc=fermentum&vestibulum=justo&ante=nec&ipsum=condimentum\",\r\n \"projectDeveloper\": \"Cogibox\",\r\n \"sector\": \"Viva\",\r\n \"projectType\": \"Topicshots\",\r\n \"coveredByNDC\": 0,\r\n \"NDCLinkage\": \"Shuffletag\",\r\n \"projectStatus\": \"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\",\r\n \"projectStatusDate\": \"2022-01-19\",\r\n \"unitMetric\": \"Fuscia\",\r\n \"methodology\": \"Quatz\",\r\n \"methodologyVersion\": 43,\r\n \"validationApproach\": \"Praesent in consequat urna\",\r\n \"validationDate\": \"2022-01-19\",\r\n \"projectTag\": \"Neque\",\r\n \"estimatedAnnualAverageEmissionReduction\": \"223\",\r\n \"projectLocations\": [\r\n {\r\n \"id\": \"40ae83b1-b497-4f63-9b7d-874505b67662\",\r\n \"countryRegion\": \"United States\",\r\n \"country\": null,\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": \"2022-01-19\",\r\n \"updatedAt\": \"2022-01-19\"\r\n }\r\n ],\r\n \"qualifications\": [\r\n {\r\n \"id\": \"702cafbb-c624-4273-9cdc-c617ad5675df\",\r\n \"qualificationId\": null,\r\n \"qualificationLink\": \"https://qualification.link/1\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"type\": \"basic type\",\r\n \"label\": \"qualification 1\",\r\n \"creditingPeriodStartDate\": null,\r\n \"creditingPeriodEndDate\": null,\r\n \"warehouseUnitId\": null,\r\n \"createdAt\": \"2022-01-19\",\r\n \"updatedAt\": \"2022-01-19\"\r\n }\r\n ],\r\n \"vintages\": [\r\n {\r\n \"id\": \"3d5a8ed2-e5a7-4275-a36e-3456812e39b7\",\r\n \"startDate\": null,\r\n \"endDate\": null,\r\n \"verificationApproach\": null,\r\n \"verificationDate\": null,\r\n \"verificationBody\": \"This is verified\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": \"2022-01-19\",\r\n \"updatedAt\": \"2022-01-19\"\r\n },\r\n {\r\n \"id\": \"57c1859d-6aa4-4c57-9dfb-6438e0d4653e\",\r\n \"startDate\": null,\r\n \"endDate\": null,\r\n \"verificationApproach\": null,\r\n \"verificationDate\": null,\r\n \"verificationBody\": \"This is verified\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": \"2022-01-19\",\r\n \"updatedAt\": \"2022-01-19\"\r\n },\r\n {\r\n \"id\": \"74887b22-da3b-4c2b-b945-670319193cdd\",\r\n \"startDate\": null,\r\n \"endDate\": null,\r\n \"verificationApproach\": null,\r\n \"verificationDate\": null,\r\n \"verificationBody\": \"This is verified\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": \"2022-01-19\",\r\n \"updatedAt\": \"2022-01-19\"\r\n },\r\n {\r\n \"id\": \"7f7f23a5-3e1a-43b4-82d8-b4156b158f88\",\r\n \"startDate\": null,\r\n \"endDate\": null,\r\n \"verificationApproach\": null,\r\n \"verificationDate\": null,\r\n \"verificationBody\": \"This is verified\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": \"2022-01-19\",\r\n \"updatedAt\": \"2022-01-19\"\r\n },\r\n {\r\n \"id\": \"a6745831-5d5e-45ed-b9fe-fd6aa129df25\",\r\n \"startDate\": null,\r\n \"endDate\": null,\r\n \"verificationApproach\": null,\r\n \"verificationDate\": null,\r\n \"verificationBody\": \"This is verified\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": \"2022-01-19\",\r\n \"updatedAt\": \"2022-01-19\"\r\n }\r\n ],\r\n \"coBenefits\": [\r\n {\r\n \"id\": \"2995a129-1fad-4251-9942-7c6db2fbff74\",\r\n \"benefit\": \"TEST_COBENEFIT_4\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": null,\r\n \"updatedAt\": null\r\n },\r\n {\r\n \"id\": \"729c71bf-cc6e-4424-842f-54c2a490952a\",\r\n \"benefit\": \"TEST_COBENEFIT_3\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": null,\r\n \"updatedAt\": null\r\n },\r\n {\r\n \"id\": \"83913f9e-9876-4c4d-ac4c-10dd992d7d7f\",\r\n \"benefit\": \"TEST_COBENEFIT_5\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": null,\r\n \"updatedAt\": null\r\n },\r\n {\r\n \"id\": \"9506cf84-6f9e-437a-a099-9672e4737668\",\r\n \"benefit\": \"TEST_COBENEFIT_1\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": null,\r\n \"updatedAt\": null\r\n },\r\n {\r\n \"id\": \"f124ebef-6436-4cd4-abdd-c55e10f4d1a0\",\r\n \"benefit\": \"TEST_COBENEFIT_2\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": null,\r\n \"updatedAt\": null\r\n }\r\n ],\r\n \"relatedProjects\": [\r\n {\r\n \"id\": \"394e319e-a4d2-4ad8-a4b3-0d5b660dd8ec\",\r\n \"type\": \"Greenlam\",\r\n \"registry\": \"Ventosanzap\",\r\n \"note\": \"Donec dapibus.\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": \"2022-01-19\",\r\n \"updatedAt\": \"2022-01-19\"\r\n },\r\n {\r\n \"id\": \"39b80025-1a2c-4cda-92aa-541e8e059258\",\r\n \"type\": \"Matsoft\",\r\n \"registry\": \"Sub-Ex\",\r\n \"note\": \"Cras pellentesque volutpat dui. Maecenas tristique, est et tempus semper, est quam pharetra magna, ac consequat metus sapien ut nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris viverra diam vitae quam. Suspendisse potenti.\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": \"2022-01-19\",\r\n \"updatedAt\": \"2022-01-19\"\r\n }\r\n ]\r\n}", "options": { "raw": { "language": "json" @@ -239,113 +210,60 @@ "path": ["projects"] } }, - "response": [ - { - "name": "POST Projects with projectsPostSchema", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "name": "Content-Type", - "value": "application/json", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"originProjectId\": \"c5067a60-e329-4510-991c-b302fd00ec8d\",\r\n \"projectId\": \"c9d147e2-bc07-4e68-a76d-43424fa8cd4e\",\r\n \"program\": \"Eimbee\",\r\n \"projectName\": \"Zoomcast\",\r\n \"projectLink\": \"http://dailymotion.com/ligula/suspendisse/ornare/consequat/lectus/in.jpg?aliquam=consequat&lacus=nulla&morbi=nisl&quis=nunc&tortor=nisl&id=duis&nulla=bibendum&ultrices=felis&aliquet=sed&maecenas=interdum&leo=venenatis&odio=turpis&condimentum=enim&id=blandit&luctus=mi&nec=in&molestie=porttitor&sed=pede&justo=justo&pellentesque=eu&viverra=massa&pede=donec&ac=dapibus&diam=duis&cras=at&pellentesque=velit&volutpat=eu&dui=est&maecenas=congue&tristique=elementum&est=in&et=hac&tempus=habitasse&semper=platea&est=dictumst&quam=morbi&pharetra=vestibulum&magna=velit&ac=id&consequat=pretium&metus=iaculis&sapien=diam&ut=erat&nunc=fermentum&vestibulum=justo&ante=nec&ipsum=condimentum\",\r\n \"projectDeveloper\": \"Cogibox\",\r\n \"sector\": \"Viva\",\r\n \"projectType\": \"Topicshots\",\r\n \"coveredByNDC\": 0,\r\n \"NDCLinkage\": \"Shuffletag\",\r\n \"projectStatus\": \"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\",\r\n \"projectStatusDate\": \"2022-01-19\",\r\n \"unitMetric\": \"Fuscia\",\r\n \"methodology\": \"Quatz\",\r\n \"methodologyVersion\": 43,\r\n \"validationApproach\": \"Praesent in consequat urna\",\r\n \"validationDate\": \"2022-01-19\",\r\n \"projectTag\": \"Neque\",\r\n \"estimatedAnnualAverageEmissionReduction\": \"223\",\r\n \"projectLocations\": [\r\n {\r\n \"id\": \"40ae83b1-b497-4f63-9b7d-874505b67662\",\r\n \"countryRegion\": \"United States\",\r\n \"country\": null,\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": \"2022-01-19\",\r\n \"updatedAt\": \"2022-01-19\"\r\n }\r\n ],\r\n \"qualifications\": [\r\n {\r\n \"id\": \"702cafbb-c624-4273-9cdc-c617ad5675df\",\r\n \"qualificationId\": null,\r\n \"qualificationLink\": \"https://qualification.link/1\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"type\": \"basic type\",\r\n \"label\": \"qualification 1\",\r\n \"creditingPeriodStartDate\": null,\r\n \"creditingPeriodEndDate\": null,\r\n \"warehouseUnitId\": null,\r\n \"createdAt\": \"2022-01-19\",\r\n \"updatedAt\": \"2022-01-19\"\r\n }\r\n ],\r\n \"vintages\": [\r\n {\r\n \"id\": \"3d5a8ed2-e5a7-4275-a36e-3456812e39b7\",\r\n \"startDate\": null,\r\n \"endDate\": null,\r\n \"verificationApproach\": null,\r\n \"verificationDate\": null,\r\n \"verificationBody\": \"This is verified\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": \"2022-01-19\",\r\n \"updatedAt\": \"2022-01-19\"\r\n },\r\n {\r\n \"id\": \"57c1859d-6aa4-4c57-9dfb-6438e0d4653e\",\r\n \"startDate\": null,\r\n \"endDate\": null,\r\n \"verificationApproach\": null,\r\n \"verificationDate\": null,\r\n \"verificationBody\": \"This is verified\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": \"2022-01-19\",\r\n \"updatedAt\": \"2022-01-19\"\r\n },\r\n {\r\n \"id\": \"74887b22-da3b-4c2b-b945-670319193cdd\",\r\n \"startDate\": null,\r\n \"endDate\": null,\r\n \"verificationApproach\": null,\r\n \"verificationDate\": null,\r\n \"verificationBody\": \"This is verified\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": \"2022-01-19\",\r\n \"updatedAt\": \"2022-01-19\"\r\n },\r\n {\r\n \"id\": \"7f7f23a5-3e1a-43b4-82d8-b4156b158f88\",\r\n \"startDate\": null,\r\n \"endDate\": null,\r\n \"verificationApproach\": null,\r\n \"verificationDate\": null,\r\n \"verificationBody\": \"This is verified\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": \"2022-01-19\",\r\n \"updatedAt\": \"2022-01-19\"\r\n },\r\n {\r\n \"id\": \"a6745831-5d5e-45ed-b9fe-fd6aa129df25\",\r\n \"startDate\": null,\r\n \"endDate\": null,\r\n \"verificationApproach\": null,\r\n \"verificationDate\": null,\r\n \"verificationBody\": \"This is verified\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": \"2022-01-19\",\r\n \"updatedAt\": \"2022-01-19\"\r\n }\r\n ],\r\n \"coBenefits\": [\r\n {\r\n \"id\": \"2995a129-1fad-4251-9942-7c6db2fbff74\",\r\n \"benefit\": \"TEST_COBENEFIT_4\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": null,\r\n \"updatedAt\": null\r\n },\r\n {\r\n \"id\": \"729c71bf-cc6e-4424-842f-54c2a490952a\",\r\n \"benefit\": \"TEST_COBENEFIT_3\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": null,\r\n \"updatedAt\": null\r\n },\r\n {\r\n \"id\": \"83913f9e-9876-4c4d-ac4c-10dd992d7d7f\",\r\n \"benefit\": \"TEST_COBENEFIT_5\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": null,\r\n \"updatedAt\": null\r\n },\r\n {\r\n \"id\": \"9506cf84-6f9e-437a-a099-9672e4737668\",\r\n \"benefit\": \"TEST_COBENEFIT_1\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": null,\r\n \"updatedAt\": null\r\n },\r\n {\r\n \"id\": \"f124ebef-6436-4cd4-abdd-c55e10f4d1a0\",\r\n \"benefit\": \"TEST_COBENEFIT_2\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": null,\r\n \"updatedAt\": null\r\n }\r\n ],\r\n \"relatedProjects\": [\r\n {\r\n \"id\": \"394e319e-a4d2-4ad8-a4b3-0d5b660dd8ec\",\r\n \"type\": \"Greenlam\",\r\n \"registry\": \"Ventosanzap\",\r\n \"note\": \"Donec dapibus.\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": \"2022-01-19\",\r\n \"updatedAt\": \"2022-01-19\"\r\n },\r\n {\r\n \"id\": \"39b80025-1a2c-4cda-92aa-541e8e059258\",\r\n \"type\": \"Matsoft\",\r\n \"registry\": \"Sub-Ex\",\r\n \"note\": \"Cras pellentesque volutpat dui. Maecenas tristique, est et tempus semper, est quam pharetra magna, ac consequat metus sapien ut nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris viverra diam vitae quam. Suspendisse potenti.\",\r\n \"warehouseProjectId\": \"81e05bfa-e93f-458f-b907-96bf170e52cd\",\r\n \"createdAt\": \"2022-01-19\",\r\n \"updatedAt\": \"2022-01-19\"\r\n }\r\n ]\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{api_url_v1}}/projects", - "host": ["{{api_url_v1}}"], - "path": ["projects"] + "response": [] + }, + { + "name": "POST Projects with required params", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"originProjectId\": \"c5067a60-e329-4510-991c-b302fd00ec8d\",\r\n \"projectId\": \"c9d147e2-bc07-4e68-a76d-43424fa8cd4e\",\r\n \"program\": \"Eimbee\",\r\n \"projectName\": \"Zoomcast\",\r\n \"projectLink\": \"http://dailymotion.com/ligula/suspendisse/ornare/consequat/lectus/in.jpg?aliquam=consequat&lacus=nulla&morbi=nisl&quis=nunc&tortor=nisl&id=duis&nulla=bibendum&ultrices=felis&aliquet=sed&maecenas=interdum&leo=venenatis&odio=turpis&condimentum=enim&id=blandit&luctus=mi&nec=in&molestie=porttitor&sed=pede&justo=justo&pellentesque=eu&viverra=massa&pede=donec&ac=dapibus&diam=duis&cras=at&pellentesque=velit&volutpat=eu&dui=est&maecenas=congue&tristique=elementum&est=in&et=hac&tempus=habitasse&semper=platea&est=dictumst&quam=morbi&pharetra=vestibulum&magna=velit&ac=id&consequat=pretium&metus=iaculis&sapien=diam&ut=erat&nunc=fermentum&vestibulum=justo&ante=nec&ipsum=condimentum\",\r\n \"projectDeveloper\": \"Cogibox\",\r\n \"sector\": \"Viva\",\r\n \"projectType\": \"Phasellus\",\r\n \"coveredByNDC\": 0,\r\n \"NDCLinkage\": \"Shuffletag\",\r\n \"projectStatus\": \"Nulla et mauris pulvinar, vulputate orci quis, porttitor felis.\",\r\n \"projectStatusDate\": \"2022-01-19\",\r\n \"unitMetric\": \"Fuscia\",\r\n \"methodology\": \"Quatz\",\r\n \"methodologyVersion\": 43,\r\n \"validationApproach\": \"Etiam at ex nisl\",\r\n \"validationDate\": \"2022-01-19\",\r\n \"projectTag\": \"Kaymbo\",\r\n \"estimatedAnnualAverageEmissionReduction\": \"100\"\r\n}", + "options": { + "raw": { + "language": "json" } - }, - "_postman_previewlanguage": null, - "header": null, - "cookie": [], - "body": "" + } }, - { - "name": "POST Projects with required params", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "name": "Content-Type", - "value": "application/json", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"originProjectId\": \"c5067a60-e329-4510-991c-b302fd00ec8d\",\r\n \"projectId\": \"c9d147e2-bc07-4e68-a76d-43424fa8cd4e\",\r\n \"program\": \"Eimbee\",\r\n \"projectName\": \"Zoomcast\",\r\n \"projectLink\": \"http://dailymotion.com/ligula/suspendisse/ornare/consequat/lectus/in.jpg?aliquam=consequat&lacus=nulla&morbi=nisl&quis=nunc&tortor=nisl&id=duis&nulla=bibendum&ultrices=felis&aliquet=sed&maecenas=interdum&leo=venenatis&odio=turpis&condimentum=enim&id=blandit&luctus=mi&nec=in&molestie=porttitor&sed=pede&justo=justo&pellentesque=eu&viverra=massa&pede=donec&ac=dapibus&diam=duis&cras=at&pellentesque=velit&volutpat=eu&dui=est&maecenas=congue&tristique=elementum&est=in&et=hac&tempus=habitasse&semper=platea&est=dictumst&quam=morbi&pharetra=vestibulum&magna=velit&ac=id&consequat=pretium&metus=iaculis&sapien=diam&ut=erat&nunc=fermentum&vestibulum=justo&ante=nec&ipsum=condimentum\",\r\n \"projectDeveloper\": \"Cogibox\",\r\n \"sector\": \"Viva\",\r\n \"projectType\": \"Phasellus\",\r\n \"coveredByNDC\": 0,\r\n \"NDCLinkage\": \"Shuffletag\",\r\n \"projectStatus\": \"Nulla et mauris pulvinar, vulputate orci quis, porttitor felis.\",\r\n \"projectStatusDate\": \"2022-01-19\",\r\n \"unitMetric\": \"Fuscia\",\r\n \"methodology\": \"Quatz\",\r\n \"methodologyVersion\": 43,\r\n \"validationApproach\": \"Etiam at ex nisl\",\r\n \"validationDate\": \"2022-01-19\",\r\n \"projectTag\": \"Kaymbo\",\r\n \"estimatedAnnualAverageEmissionReduction\": \"100\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{api_url_v1}}/projects", - "host": ["{{api_url_v1}}"], - "path": ["projects"] + "url": { + "raw": "{{api_url_v1}}/projects", + "host": ["{{api_url_v1}}"], + "path": ["projects"] + } + }, + "response": [] + }, + { + "name": "POST Projects missing required param \"sector\"", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"originProjectId\": \"c5067a60-e329-4510-991c-b302fd00ec8d\",\r\n \"projectId\": \"11954678-f7a5-47d2-94f8-f4f3138a529c\",\r\n \"program\": \"Eimbee\",\r\n \"projectName\": \"Zoomcast\",\r\n \"projectLink\": \"http://dailymotion.com/ligula/suspendisse/ornare/consequat/lectus/in.jpg?aliquam=consequat&lacus=nulla&morbi=nisl&quis=nunc&tortor=nisl&id=duis&nulla=bibendum&ultrices=felis&aliquet=sed&maecenas=interdum&leo=venenatis&odio=turpis&condimentum=enim&id=blandit&luctus=mi&nec=in&molestie=porttitor&sed=pede&justo=justo&pellentesque=eu&viverra=massa&pede=donec&ac=dapibus&diam=duis&cras=at&pellentesque=velit&volutpat=eu&dui=est&maecenas=congue&tristique=elementum&est=in&et=hac&tempus=habitasse&semper=platea&est=dictumst&quam=morbi&pharetra=vestibulum&magna=velit&ac=id&consequat=pretium&metus=iaculis&sapien=diam&ut=erat&nunc=fermentum&vestibulum=justo&ante=nec&ipsum=condimentum\",\r\n \"projectDeveloper\": \"Cogibox\",\r\n \"projectType\": \"Topicshots\",\r\n \"coveredByNDC\": 0,\r\n \"NDCLinkage\": \"Shuffletag\",\r\n \"projectStatus\": \"I know many children ask for a pony, but I wanted a bicycle with rockets strapped to it.\",\r\n \"projectStatusDate\": \"2022-01-19\",\r\n \"unitMetric\": \"Fuscia\",\r\n \"methodology\": \"Quatz\",\r\n \"methodologyVersion\": 43,\r\n \"validationApproach\": \"He waited for the stop sign to turn to a go sign.\",\r\n \"validationDate\": \"2022-01-19\",\r\n \"projectTag\": \"Kaymbo\",\r\n \"estimatedAnnualAverageEmissionReduction\": \"60\"\r\n}", + "options": { + "raw": { + "language": "json" } - }, - "_postman_previewlanguage": null, - "header": null, - "cookie": [], - "body": "" + } }, - { - "name": "POST Projects missing required param \"sector\"", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "name": "Content-Type", - "value": "application/json", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"originProjectId\": \"c5067a60-e329-4510-991c-b302fd00ec8d\",\r\n \"projectId\": \"11954678-f7a5-47d2-94f8-f4f3138a529c\",\r\n \"program\": \"Eimbee\",\r\n \"projectName\": \"Zoomcast\",\r\n \"projectLink\": \"http://dailymotion.com/ligula/suspendisse/ornare/consequat/lectus/in.jpg?aliquam=consequat&lacus=nulla&morbi=nisl&quis=nunc&tortor=nisl&id=duis&nulla=bibendum&ultrices=felis&aliquet=sed&maecenas=interdum&leo=venenatis&odio=turpis&condimentum=enim&id=blandit&luctus=mi&nec=in&molestie=porttitor&sed=pede&justo=justo&pellentesque=eu&viverra=massa&pede=donec&ac=dapibus&diam=duis&cras=at&pellentesque=velit&volutpat=eu&dui=est&maecenas=congue&tristique=elementum&est=in&et=hac&tempus=habitasse&semper=platea&est=dictumst&quam=morbi&pharetra=vestibulum&magna=velit&ac=id&consequat=pretium&metus=iaculis&sapien=diam&ut=erat&nunc=fermentum&vestibulum=justo&ante=nec&ipsum=condimentum\",\r\n \"projectDeveloper\": \"Cogibox\",\r\n \"projectType\": \"Topicshots\",\r\n \"coveredByNDC\": 0,\r\n \"NDCLinkage\": \"Shuffletag\",\r\n \"projectStatus\": \"Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae\",\r\n \"projectStatusDate\": \"2022-01-19\",\r\n \"unitMetric\": \"Fuscia\",\r\n \"methodology\": \"Quatz\",\r\n \"methodologyVersion\": 43,\r\n \"validationApproach\": \"Quisque dignissim velit vel metus congue, et interdum nulla ullamcorper.\",\r\n \"validationDate\": \"2022-01-19\",\r\n \"projectTag\": \"Kaymbo\",\r\n \"estimatedAnnualAverageEmissionReduction\": \"60\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{api_url_v1}}/projects", - "host": ["{{api_url_v1}}"], - "path": ["projects"] - } - }, - "_postman_previewlanguage": null, - "header": null, - "cookie": [], - "body": null + "url": { + "raw": "{{api_url_v1}}/projects", + "host": ["{{api_url_v1}}"], + "path": ["projects"] } - ] + }, + "response": [] }, { - "name": "PUT Projects", + "name": "PUT Projects program, sector, methodologyVersion, projectStatusDate, validationDate", "request": { "method": "PUT", "header": [], "body": { "mode": "raw", - "raw": "{\r\n \"warehouseProjectId\": \"897891e2-cc66-4867-8da2-c17d69d018cb\",\r\n \"originProjectId\": \"c5067a60-e329-4510-991c-b302fd00ec8d\",\r\n \"projectId\": \"c9d147e2-bc07-4e68-a76d-43424fa8cd4e\",\r\n \"program\": \"Eimbee\",\r\n \"projectName\": \"Zoomcast\",\r\n \"projectLink\": \"https://www.chia.net/technology/\",\r\n \"projectDeveloper\": \"Cogibox\",\r\n \"sector\": \"Viva\",\r\n \"projectType\": \"Topicshots\",\r\n \"coveredByNDC\": 0,\r\n \"NDCLinkage\": \"Shuffletag\",\r\n \"projectStatus\": \"His son quipped that power bars were nothing more than adult candy bars.\",\r\n \"projectStatusDate\": \"2020-01-19\",\r\n \"unitMetric\": \"Fuscia\",\r\n \"methodology\": \"Quatz\",\r\n \"methodologyVersion\": 43,\r\n \"validationApproach\": \"This made him feel like an old-style rootbeer float smells.\",\r\n \"validationDate\": \"2022-03-22\",\r\n \"projectTag\": \"Kaymbo\",\r\n \"estimatedAnnualAverageEmissionReduction\": \"60\",\r\n \"projectLocations\": [\r\n {\r\n \"id\": \"b41d0f89-2f71-4bde-b6d0-5cf77802c3fc\",\r\n \"countryRegion\": \"United States\",\r\n \"country\": null,\r\n \"warehouseProjectId\": \"897891e2-cc66-4867-8da2-c17d69d018cb\",\r\n \"createdAt\": \"2022-01-18T00:05:45.701Z\",\r\n \"updatedAt\": \"2022-01-18T00:05:45.701Z\"\r\n }\r\n ],\r\n \"relatedProjects\": [\r\n {\r\n \"id\": \"54171fde-bbad-4483-9908-79707912cc22\",\r\n \"type\": \"Greenlam\",\r\n \"registry\": \"Aerified\",\r\n \"note\": \"Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi. Cras non velit nec nisi vulputate nonummy. Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque. Quisque porta volutpat erat.\",\r\n \"warehouseProjectId\": \"897891e2-cc66-4867-8da2-c17d69d018cb\",\r\n \"createdAt\": \"2022-01-18T00:05:45.701Z\",\r\n \"updatedAt\": \"2022-01-18T00:05:45.701Z\"\r\n },\r\n {\r\n \"id\": \"aa537d7f-d693-4831-9d88-8a045eebef76\",\r\n \"type\": \"Lotstring\",\r\n \"registry\": \"Y-find\",\r\n \"note\": \"In hac habitasse platea dictumst. Morbi vestibulum, velit id pretium iaculis, diam erat fermentum justo, nec condimentum neque sapien placerat ante. Nulla justo. Aliquam quis turpis eget elit sodales scelerisque. Mauris sit amet eros. Suspendisse accumsan tortor quis turpis. Sed ante. Vivamus tortor. Duis mattis egestas metus.\",\r\n \"warehouseProjectId\": \"897891e2-cc66-4867-8da2-c17d69d018cb\",\r\n \"createdAt\": \"2022-01-18T00:05:45.701Z\",\r\n \"updatedAt\": \"2022-01-18T00:05:45.701Z\"\r\n }\r\n ]\r\n}", + "raw": "{\r\n \"warehouseProjectId\": \"8a02a620-8be8-44f9-ba90-eff00ccc3a70\",\r\n \"originProjectId\": \"c5067a60-e329-4510-991c-b302fd00ec8d\",\r\n \"projectId\": \"c9d147e2-bc07-4e68-a76d-43424fa8cd4e\",\r\n \"program\": \"Lorem\",\r\n \"projectName\": \"Zoomcast\",\r\n \"projectLink\": \"http://dailymotion.com/ligula/suspendisse/ornare/consequat/lectus/in.jpg?aliquam=consequat&lacus=nulla&morbi=nisl&quis=nunc&tortor=nisl&id=duis&nulla=bibendum&ultrices=felis&aliquet=sed&maecenas=interdum&leo=venenatis&odio=turpis&condimentum=enim&id=blandit&luctus=mi&nec=in&molestie=porttitor&sed=pede&justo=justo&pellentesque=eu&viverra=massa&pede=donec&ac=dapibus&diam=duis&cras=at&pellentesque=velit&volutpat=eu&dui=est&maecenas=congue&tristique=elementum&est=in&et=hac&tempus=habitasse&semper=platea&est=dictumst&quam=morbi&pharetra=vestibulum&magna=velit&ac=id&consequat=pretium&metus=iaculis&sapien=diam&ut=erat&nunc=fermentum&vestibulum=justo&ante=nec&ipsum=condimentum\",\r\n \"projectDeveloper\": \"Cogibox\",\r\n \"sector\": \"Seven\",\r\n \"projectType\": \"Topicshots\",\r\n \"coveredByNDC\": 1,\r\n \"NDCLinkage\": \"Shuffletag\",\r\n \"projectStatus\": \"They desperately needed another drummer since the current one only knew how to play bongos.\",\r\n \"projectStatusDate\": \"2020-01-19\",\r\n \"unitMetric\": \"Fuscia\",\r\n \"methodology\": \"Quatz\",\r\n \"methodologyVersion\": 22,\r\n \"validationApproach\": \"The small white buoys marked the location of hundreds of crab pots.\",\r\n \"validationDate\": \"2022-03-22\",\r\n \"projectTag\": \"Kaymbo\",\r\n \"estimatedAnnualAverageEmissionReduction\": \"60\",\r\n \"projectLocations\": [\r\n {\r\n \"id\": \"8f23fd77-d19f-4083-b7be-949288e88a36\",\r\n \"countryRegion\": \"China\",\r\n \"country\": null,\r\n \"warehouseProjectId\": \"8a02a620-8be8-44f9-ba90-eff00ccc3a70\",\r\n \"createdAt\": \"2022-01-18T00:05:45.701Z\",\r\n \"updatedAt\": \"2022-01-18T00:05:45.701Z\"\r\n }\r\n ]\r\n}", "options": { "raw": { "language": "json" @@ -358,72 +276,29 @@ "path": ["projects"] } }, - "response": [ - { - "name": "PUT Projects program, sector, methodologyVersion, projectStatusDate, validationDate", - "originalRequest": { - "method": "PUT", - "header": [ - { - "key": "Content-Type", - "name": "Content-Type", - "value": "application/json", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"warehouseProjectId\": \"8a02a620-8be8-44f9-ba90-eff00ccc3a70\",\r\n \"originProjectId\": \"c5067a60-e329-4510-991c-b302fd00ec8d\",\r\n \"projectId\": \"c9d147e2-bc07-4e68-a76d-43424fa8cd4e\",\r\n \"program\": \"Lorem\",\r\n \"projectName\": \"Zoomcast\",\r\n \"projectLink\": \"http://dailymotion.com/ligula/suspendisse/ornare/consequat/lectus/in.jpg?aliquam=consequat&lacus=nulla&morbi=nisl&quis=nunc&tortor=nisl&id=duis&nulla=bibendum&ultrices=felis&aliquet=sed&maecenas=interdum&leo=venenatis&odio=turpis&condimentum=enim&id=blandit&luctus=mi&nec=in&molestie=porttitor&sed=pede&justo=justo&pellentesque=eu&viverra=massa&pede=donec&ac=dapibus&diam=duis&cras=at&pellentesque=velit&volutpat=eu&dui=est&maecenas=congue&tristique=elementum&est=in&et=hac&tempus=habitasse&semper=platea&est=dictumst&quam=morbi&pharetra=vestibulum&magna=velit&ac=id&consequat=pretium&metus=iaculis&sapien=diam&ut=erat&nunc=fermentum&vestibulum=justo&ante=nec&ipsum=condimentum\",\r\n \"projectDeveloper\": \"Cogibox\",\r\n \"sector\": \"Seven\",\r\n \"projectType\": \"Topicshots\",\r\n \"coveredByNDC\": 1,\r\n \"NDCLinkage\": \"Shuffletag\",\r\n \"projectStatus\": \"They desperately needed another drummer since the current one only knew how to play bongos.\",\r\n \"projectStatusDate\": \"2020-01-19\",\r\n \"unitMetric\": \"Fuscia\",\r\n \"methodology\": \"Quatz\",\r\n \"methodologyVersion\": 22,\r\n \"validationApproach\": \"The small white buoys marked the location of hundreds of crab pots.\",\r\n \"validationDate\": \"2022-03-22\",\r\n \"projectTag\": \"Kaymbo\",\r\n \"estimatedAnnualAverageEmissionReduction\": \"60\",\r\n \"projectLocations\": [\r\n {\r\n \"id\": \"8f23fd77-d19f-4083-b7be-949288e88a36\",\r\n \"countryRegion\": \"China\",\r\n \"country\": null,\r\n \"warehouseProjectId\": \"8a02a620-8be8-44f9-ba90-eff00ccc3a70\",\r\n \"createdAt\": \"2022-01-18T00:05:45.701Z\",\r\n \"updatedAt\": \"2022-01-18T00:05:45.701Z\"\r\n }\r\n ]\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{api_url_v1}}/projects", - "host": ["{{api_url_v1}}"], - "path": ["projects"] + "response": [] + }, + { + "name": "PUT Projects projectLink", + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"warehouseProjectId\": \"897891e2-cc66-4867-8da2-c17d69d018cb\",\r\n \"originProjectId\": \"c5067a60-e329-4510-991c-b302fd00ec8d\",\r\n \"projectId\": \"c9d147e2-bc07-4e68-a76d-43424fa8cd4e\",\r\n \"program\": \"Eimbee\",\r\n \"projectName\": \"Zoomcast\",\r\n \"projectLink\": \"https://www.chia.net/technology/\",\r\n \"projectDeveloper\": \"Cogibox\",\r\n \"sector\": \"Viva\",\r\n \"projectType\": \"Topicshots\",\r\n \"coveredByNDC\": 0,\r\n \"NDCLinkage\": \"Shuffletag\",\r\n \"projectStatus\": \"His son quipped that power bars were nothing more than adult candy bars.\",\r\n \"projectStatusDate\": \"2020-01-19\",\r\n \"unitMetric\": \"Fuscia\",\r\n \"methodology\": \"Quatz\",\r\n \"methodologyVersion\": 43,\r\n \"validationApproach\": \"This made him feel like an old-style rootbeer float smells.\",\r\n \"validationDate\": \"2022-03-22\",\r\n \"projectTag\": \"Kaymbo\",\r\n \"estimatedAnnualAverageEmissionReduction\": \"60\",\r\n \"projectLocations\": [\r\n {\r\n \"id\": \"b41d0f89-2f71-4bde-b6d0-5cf77802c3fc\",\r\n \"countryRegion\": \"United States\",\r\n \"country\": null,\r\n \"warehouseProjectId\": \"897891e2-cc66-4867-8da2-c17d69d018cb\",\r\n \"createdAt\": \"2022-01-18T00:05:45.701Z\",\r\n \"updatedAt\": \"2022-01-18T00:05:45.701Z\"\r\n }\r\n ],\r\n \"relatedProjects\": [\r\n {\r\n \"id\": \"54171fde-bbad-4483-9908-79707912cc22\",\r\n \"type\": \"Greenlam\",\r\n \"registry\": \"Aerified\",\r\n \"note\": \"Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi. Cras non velit nec nisi vulputate nonummy. Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque. Quisque porta volutpat erat.\",\r\n \"warehouseProjectId\": \"897891e2-cc66-4867-8da2-c17d69d018cb\",\r\n \"createdAt\": \"2022-01-18T00:05:45.701Z\",\r\n \"updatedAt\": \"2022-01-18T00:05:45.701Z\"\r\n },\r\n {\r\n \"id\": \"aa537d7f-d693-4831-9d88-8a045eebef76\",\r\n \"type\": \"Lotstring\",\r\n \"registry\": \"Y-find\",\r\n \"note\": \"In hac habitasse platea dictumst. Morbi vestibulum, velit id pretium iaculis, diam erat fermentum justo, nec condimentum neque sapien placerat ante. Nulla justo. Aliquam quis turpis eget elit sodales scelerisque. Mauris sit amet eros. Suspendisse accumsan tortor quis turpis. Sed ante. Vivamus tortor. Duis mattis egestas metus.\",\r\n \"warehouseProjectId\": \"897891e2-cc66-4867-8da2-c17d69d018cb\",\r\n \"createdAt\": \"2022-01-18T00:05:45.701Z\",\r\n \"updatedAt\": \"2022-01-18T00:05:45.701Z\"\r\n }\r\n ]\r\n}", + "options": { + "raw": { + "language": "json" } - }, - "_postman_previewlanguage": null, - "header": null, - "cookie": [], - "body": null + } }, - { - "name": "PUT Projects projectLink", - "originalRequest": { - "method": "PUT", - "header": [ - { - "key": "Content-Type", - "name": "Content-Type", - "value": "application/json", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\r\n \"warehouseProjectId\": \"897891e2-cc66-4867-8da2-c17d69d018cb\",\r\n \"originProjectId\": \"c5067a60-e329-4510-991c-b302fd00ec8d\",\r\n \"projectId\": \"c9d147e2-bc07-4e68-a76d-43424fa8cd4e\",\r\n \"program\": \"Eimbee\",\r\n \"projectName\": \"Zoomcast\",\r\n \"projectLink\": \"https://www.chia.net/technology/\",\r\n \"projectDeveloper\": \"Cogibox\",\r\n \"sector\": \"Viva\",\r\n \"projectType\": \"Topicshots\",\r\n \"coveredByNDC\": 0,\r\n \"NDCLinkage\": \"Shuffletag\",\r\n \"projectStatus\": \"His son quipped that power bars were nothing more than adult candy bars.\",\r\n \"projectStatusDate\": \"2020-01-19\",\r\n \"unitMetric\": \"Fuscia\",\r\n \"methodology\": \"Quatz\",\r\n \"methodologyVersion\": 43,\r\n \"validationApproach\": \"This made him feel like an old-style rootbeer float smells.\",\r\n \"validationDate\": \"2022-03-22\",\r\n \"projectTag\": \"Kaymbo\",\r\n \"estimatedAnnualAverageEmissionReduction\": \"60\",\r\n \"projectLocations\": [\r\n {\r\n \"id\": \"b41d0f89-2f71-4bde-b6d0-5cf77802c3fc\",\r\n \"countryRegion\": \"United States\",\r\n \"country\": null,\r\n \"warehouseProjectId\": \"897891e2-cc66-4867-8da2-c17d69d018cb\",\r\n \"createdAt\": \"2022-01-18T00:05:45.701Z\",\r\n \"updatedAt\": \"2022-01-18T00:05:45.701Z\"\r\n }\r\n ],\r\n \"relatedProjects\": [\r\n {\r\n \"id\": \"54171fde-bbad-4483-9908-79707912cc22\",\r\n \"type\": \"Greenlam\",\r\n \"registry\": \"Aerified\",\r\n \"note\": \"Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi. Cras non velit nec nisi vulputate nonummy. Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque. Quisque porta volutpat erat.\",\r\n \"warehouseProjectId\": \"897891e2-cc66-4867-8da2-c17d69d018cb\",\r\n \"createdAt\": \"2022-01-18T00:05:45.701Z\",\r\n \"updatedAt\": \"2022-01-18T00:05:45.701Z\"\r\n },\r\n {\r\n \"id\": \"aa537d7f-d693-4831-9d88-8a045eebef76\",\r\n \"type\": \"Lotstring\",\r\n \"registry\": \"Y-find\",\r\n \"note\": \"In hac habitasse platea dictumst. Morbi vestibulum, velit id pretium iaculis, diam erat fermentum justo, nec condimentum neque sapien placerat ante. Nulla justo. Aliquam quis turpis eget elit sodales scelerisque. Mauris sit amet eros. Suspendisse accumsan tortor quis turpis. Sed ante. Vivamus tortor. Duis mattis egestas metus.\",\r\n \"warehouseProjectId\": \"897891e2-cc66-4867-8da2-c17d69d018cb\",\r\n \"createdAt\": \"2022-01-18T00:05:45.701Z\",\r\n \"updatedAt\": \"2022-01-18T00:05:45.701Z\"\r\n }\r\n ]\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{api_url_v1}}/projects", - "host": ["{{api_url_v1}}"], - "path": ["projects"] - } - }, - "_postman_previewlanguage": null, - "header": null, - "cookie": [], - "body": null + "url": { + "raw": "{{api_url_v1}}/projects", + "host": ["{{api_url_v1}}"], + "path": ["projects"] } - ] + }, + "response": [] }, { "name": "DELETE Projects", @@ -446,6 +321,52 @@ } }, "response": [] + }, + { + "name": "POST Projects batch - create projects", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "csv", + "type": "file", + "src": "/C:/Users/alexa/Desktop/createProjects.csv" + } + ] + }, + "url": { + "raw": "{{api_url_v1}}/projects/batch", + "host": ["{{api_url_v1}}"], + "path": ["projects", "batch"] + } + }, + "response": [] + }, + { + "name": "POST Projects batch - update projects", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "csv", + "type": "file", + "src": "/C:/Users/alexa/Desktop/updateProjects.csv" + } + ] + }, + "url": { + "raw": "{{api_url_v1}}/projects/batch", + "host": ["{{api_url_v1}}"], + "path": ["projects", "batch"] + } + }, + "response": [] } ], "auth": { diff --git a/docs/postman/createProjects.csv b/docs/postman/createProjects.csv new file mode 100644 index 00000000..4b3f4efe --- /dev/null +++ b/docs/postman/createProjects.csv @@ -0,0 +1,10 @@ +originProjectId,projectId,program,projectName,projectLink,projectDeveloper,sector,projectType,coveredByNDC,NDCLinkage,projectStatus,projectStatusDate,unitMetric,methodology,methodologyVersion,validationApproach,validationDate,projectTag,estimatedAnnualAverageEmissionReduction,projectLocations,qualifications,vintages,coBenefits,relatedProjects +c5067a60-e329-4510-991c-b302fd00ec8d,c9d147e2-bc07-4e68-a76d-43424fa8cd4e,Eimbee,Zoomcast,http://dailymotion.com/ligula/suspendisse/ornare/consequat/lectus/in.jpg?aliquam=consequat&lacus=nulla&morbi=nisl&quis=nunc&tortor=nisl&id=duis&nulla=bibendum&ultrices=felis&aliquet=sed&maecenas=interdum&leo=venenatis&odio=turpis&condimentum=enim&id=blandit&luctus=mi&nec=in&molestie=porttitor&sed=pede&justo=justo&pellentesque=eu&viverra=massa&pede=donec&ac=dapibus&diam=duis&cras=at&pellentesque=velit&volutpat=eu&dui=est&maecenas=congue&tristique=elementum&est=in&et=hac&tempus=habitasse&semper=platea&est=dictumst&quam=morbi&pharetra=vestibulum&magna=velit&ac=id&consequat=pretium&metus=iaculis&sapien=diam&ut=erat&nunc=fermentum&vestibulum=justo&ante=nec&ipsum=condimentum,Cogibox,Viva,Topicshots,0,Shuffletag,"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",1/19/2022,Fuscia,Quatz,43,Praesent in consequat urna,1/19/2022,Neque,120,United States,https://qualification.link/1,"3d5a8ed2-e5a7-4275-a36e-3456812e39b7,57c1859d-6aa4-4c57-9dfb-6438e0d4653e",TEST_COBENEFIT_4,394e319e-a4d2-4ad8-a4b3-0d5b660dd8ec +c5067a60-e329-4510-991c-b302fd00ec8d,c9d147e2-bc07-4e68-a76d-43424fa8cd4e,Eimbee,Zoomcast,http://dailymotion.com/ligula/suspendisse/ornare/consequat/lectus/in.jpg?aliquam=consequat&lacus=nulla&morbi=nisl&quis=nunc&tortor=nisl&id=duis&nulla=bibendum&ultrices=felis&aliquet=sed&maecenas=interdum&leo=venenatis&odio=turpis&condimentum=enim&id=blandit&luctus=mi&nec=in&molestie=porttitor&sed=pede&justo=justo&pellentesque=eu&viverra=massa&pede=donec&ac=dapibus&diam=duis&cras=at&pellentesque=velit&volutpat=eu&dui=est&maecenas=congue&tristique=elementum&est=in&et=hac&tempus=habitasse&semper=platea&est=dictumst&quam=morbi&pharetra=vestibulum&magna=velit&ac=id&consequat=pretium&metus=iaculis&sapien=diam&ut=erat&nunc=fermentum&vestibulum=justo&ante=nec&ipsum=condimentum,Cogibox,Viva,Topicshots,1,Shuffletag,"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",1/20/2022,Fuscia,Quatz,44,Praesent in consequat urna,1/20/2022,Neque,121,United States,https://qualification.link/2,"3d5a8ed2-e5a7-4275-a36e-3456812e39b7,57c1859d-6aa4-4c57-9dfb-6438e0d4653e",TEST_COBENEFIT_5,394e319e-a4d2-4ad8-a4b3-0d5b660dd8ec +c5067a60-e329-4510-991c-b302fd00ec8d,c9d147e2-bc07-4e68-a76d-43424fa8cd4e,Eimbee,Zoomcast,http://dailymotion.com/ligula/suspendisse/ornare/consequat/lectus/in.jpg?aliquam=consequat&lacus=nulla&morbi=nisl&quis=nunc&tortor=nisl&id=duis&nulla=bibendum&ultrices=felis&aliquet=sed&maecenas=interdum&leo=venenatis&odio=turpis&condimentum=enim&id=blandit&luctus=mi&nec=in&molestie=porttitor&sed=pede&justo=justo&pellentesque=eu&viverra=massa&pede=donec&ac=dapibus&diam=duis&cras=at&pellentesque=velit&volutpat=eu&dui=est&maecenas=congue&tristique=elementum&est=in&et=hac&tempus=habitasse&semper=platea&est=dictumst&quam=morbi&pharetra=vestibulum&magna=velit&ac=id&consequat=pretium&metus=iaculis&sapien=diam&ut=erat&nunc=fermentum&vestibulum=justo&ante=nec&ipsum=condimentum,Cogibox,Viva,Topicshots,2,Shuffletag,"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",1/21/2022,Fuscia,Quatz,45,Praesent in consequat urna,1/21/2022,Neque,122,United States,https://qualification.link/3,"3d5a8ed2-e5a7-4275-a36e-3456812e39b7,57c1859d-6aa4-4c57-9dfb-6438e0d4653e",TEST_COBENEFIT_6,394e319e-a4d2-4ad8-a4b3-0d5b660dd8ec +c5067a60-e329-4510-991c-b302fd00ec8d,c9d147e2-bc07-4e68-a76d-43424fa8cd4e,Eimbee,Zoomcast,http://dailymotion.com/ligula/suspendisse/ornare/consequat/lectus/in.jpg?aliquam=consequat&lacus=nulla&morbi=nisl&quis=nunc&tortor=nisl&id=duis&nulla=bibendum&ultrices=felis&aliquet=sed&maecenas=interdum&leo=venenatis&odio=turpis&condimentum=enim&id=blandit&luctus=mi&nec=in&molestie=porttitor&sed=pede&justo=justo&pellentesque=eu&viverra=massa&pede=donec&ac=dapibus&diam=duis&cras=at&pellentesque=velit&volutpat=eu&dui=est&maecenas=congue&tristique=elementum&est=in&et=hac&tempus=habitasse&semper=platea&est=dictumst&quam=morbi&pharetra=vestibulum&magna=velit&ac=id&consequat=pretium&metus=iaculis&sapien=diam&ut=erat&nunc=fermentum&vestibulum=justo&ante=nec&ipsum=condimentum,Cogibox,Viva,Topicshots,3,Shuffletag,"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",1/22/2022,Fuscia,Quatz,46,Praesent in consequat urna,1/22/2022,Neque,123,United States,https://qualification.link/4,"3d5a8ed2-e5a7-4275-a36e-3456812e39b7,57c1859d-6aa4-4c57-9dfb-6438e0d4653e",TEST_COBENEFIT_7,394e319e-a4d2-4ad8-a4b3-0d5b660dd8ec +c5067a60-e329-4510-991c-b302fd00ec8d,c9d147e2-bc07-4e68-a76d-43424fa8cd4e,Eimbee,Zoomcast,http://dailymotion.com/ligula/suspendisse/ornare/consequat/lectus/in.jpg?aliquam=consequat&lacus=nulla&morbi=nisl&quis=nunc&tortor=nisl&id=duis&nulla=bibendum&ultrices=felis&aliquet=sed&maecenas=interdum&leo=venenatis&odio=turpis&condimentum=enim&id=blandit&luctus=mi&nec=in&molestie=porttitor&sed=pede&justo=justo&pellentesque=eu&viverra=massa&pede=donec&ac=dapibus&diam=duis&cras=at&pellentesque=velit&volutpat=eu&dui=est&maecenas=congue&tristique=elementum&est=in&et=hac&tempus=habitasse&semper=platea&est=dictumst&quam=morbi&pharetra=vestibulum&magna=velit&ac=id&consequat=pretium&metus=iaculis&sapien=diam&ut=erat&nunc=fermentum&vestibulum=justo&ante=nec&ipsum=condimentum,Cogibox,Viva,Topicshots,4,Shuffletag,"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",1/23/2022,Fuscia,Quatz,47,Praesent in consequat urna,1/23/2022,Neque,124,United States,https://qualification.link/5,"3d5a8ed2-e5a7-4275-a36e-3456812e39b7,57c1859d-6aa4-4c57-9dfb-6438e0d4653e",TEST_COBENEFIT_8,394e319e-a4d2-4ad8-a4b3-0d5b660dd8ec +c5067a60-e329-4510-991c-b302fd00ec8d,c9d147e2-bc07-4e68-a76d-43424fa8cd4e,Eimbee,Zoomcast,http://dailymotion.com/ligula/suspendisse/ornare/consequat/lectus/in.jpg?aliquam=consequat&lacus=nulla&morbi=nisl&quis=nunc&tortor=nisl&id=duis&nulla=bibendum&ultrices=felis&aliquet=sed&maecenas=interdum&leo=venenatis&odio=turpis&condimentum=enim&id=blandit&luctus=mi&nec=in&molestie=porttitor&sed=pede&justo=justo&pellentesque=eu&viverra=massa&pede=donec&ac=dapibus&diam=duis&cras=at&pellentesque=velit&volutpat=eu&dui=est&maecenas=congue&tristique=elementum&est=in&et=hac&tempus=habitasse&semper=platea&est=dictumst&quam=morbi&pharetra=vestibulum&magna=velit&ac=id&consequat=pretium&metus=iaculis&sapien=diam&ut=erat&nunc=fermentum&vestibulum=justo&ante=nec&ipsum=condimentum,Cogibox,Viva,Topicshots,5,Shuffletag,"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",1/24/2022,Fuscia,Quatz,48,Praesent in consequat urna,1/24/2022,Neque,125,United States,https://qualification.link/6,"3d5a8ed2-e5a7-4275-a36e-3456812e39b7,57c1859d-6aa4-4c57-9dfb-6438e0d4653e",TEST_COBENEFIT_9,394e319e-a4d2-4ad8-a4b3-0d5b660dd8ec +c5067a60-e329-4510-991c-b302fd00ec8d,c9d147e2-bc07-4e68-a76d-43424fa8cd4e,Eimbee,Zoomcast,http://dailymotion.com/ligula/suspendisse/ornare/consequat/lectus/in.jpg?aliquam=consequat&lacus=nulla&morbi=nisl&quis=nunc&tortor=nisl&id=duis&nulla=bibendum&ultrices=felis&aliquet=sed&maecenas=interdum&leo=venenatis&odio=turpis&condimentum=enim&id=blandit&luctus=mi&nec=in&molestie=porttitor&sed=pede&justo=justo&pellentesque=eu&viverra=massa&pede=donec&ac=dapibus&diam=duis&cras=at&pellentesque=velit&volutpat=eu&dui=est&maecenas=congue&tristique=elementum&est=in&et=hac&tempus=habitasse&semper=platea&est=dictumst&quam=morbi&pharetra=vestibulum&magna=velit&ac=id&consequat=pretium&metus=iaculis&sapien=diam&ut=erat&nunc=fermentum&vestibulum=justo&ante=nec&ipsum=condimentum,Cogibox,Viva,Topicshots,6,Shuffletag,"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",1/25/2022,Fuscia,Quatz,49,Praesent in consequat urna,1/25/2022,Neque,126,United States,https://qualification.link/7,"3d5a8ed2-e5a7-4275-a36e-3456812e39b7,57c1859d-6aa4-4c57-9dfb-6438e0d4653e",TEST_COBENEFIT_10,394e319e-a4d2-4ad8-a4b3-0d5b660dd8ec +c5067a60-e329-4510-991c-b302fd00ec8d,c9d147e2-bc07-4e68-a76d-43424fa8cd4e,Eimbee,Zoomcast,http://dailymotion.com/ligula/suspendisse/ornare/consequat/lectus/in.jpg?aliquam=consequat&lacus=nulla&morbi=nisl&quis=nunc&tortor=nisl&id=duis&nulla=bibendum&ultrices=felis&aliquet=sed&maecenas=interdum&leo=venenatis&odio=turpis&condimentum=enim&id=blandit&luctus=mi&nec=in&molestie=porttitor&sed=pede&justo=justo&pellentesque=eu&viverra=massa&pede=donec&ac=dapibus&diam=duis&cras=at&pellentesque=velit&volutpat=eu&dui=est&maecenas=congue&tristique=elementum&est=in&et=hac&tempus=habitasse&semper=platea&est=dictumst&quam=morbi&pharetra=vestibulum&magna=velit&ac=id&consequat=pretium&metus=iaculis&sapien=diam&ut=erat&nunc=fermentum&vestibulum=justo&ante=nec&ipsum=condimentum,Cogibox,Viva,Topicshots,7,Shuffletag,"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",1/26/2022,Fuscia,Quatz,50,Praesent in consequat urna,1/26/2022,Neque,127,United States,https://qualification.link/8,"3d5a8ed2-e5a7-4275-a36e-3456812e39b7,57c1859d-6aa4-4c57-9dfb-6438e0d4653e",TEST_COBENEFIT_11,394e319e-a4d2-4ad8-a4b3-0d5b660dd8ec +c5067a60-e329-4510-991c-b302fd00ec8d,c9d147e2-bc07-4e68-a76d-43424fa8cd4e,Eimbee,Zoomcast,http://dailymotion.com/ligula/suspendisse/ornare/consequat/lectus/in.jpg?aliquam=consequat&lacus=nulla&morbi=nisl&quis=nunc&tortor=nisl&id=duis&nulla=bibendum&ultrices=felis&aliquet=sed&maecenas=interdum&leo=venenatis&odio=turpis&condimentum=enim&id=blandit&luctus=mi&nec=in&molestie=porttitor&sed=pede&justo=justo&pellentesque=eu&viverra=massa&pede=donec&ac=dapibus&diam=duis&cras=at&pellentesque=velit&volutpat=eu&dui=est&maecenas=congue&tristique=elementum&est=in&et=hac&tempus=habitasse&semper=platea&est=dictumst&quam=morbi&pharetra=vestibulum&magna=velit&ac=id&consequat=pretium&metus=iaculis&sapien=diam&ut=erat&nunc=fermentum&vestibulum=justo&ante=nec&ipsum=condimentum,Cogibox,Viva,Topicshots,8,Shuffletag,"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",1/27/2022,Fuscia,Quatz,51,Praesent in consequat urna,1/27/2022,Neque,128,United States,https://qualification.link/9,"3d5a8ed2-e5a7-4275-a36e-3456812e39b7,57c1859d-6aa4-4c57-9dfb-6438e0d4653e",TEST_COBENEFIT_12,394e319e-a4d2-4ad8-a4b3-0d5b660dd8ec diff --git a/docs/postman/updateProjects.csv b/docs/postman/updateProjects.csv new file mode 100644 index 00000000..e12a722a --- /dev/null +++ b/docs/postman/updateProjects.csv @@ -0,0 +1,4 @@ +warehouseUnitId,originProjectId,projectId,program,projectName,projectLink,projectDeveloper,sector,projectType,coveredByNDC,NDCLinkage,projectStatus,projectStatusDate,unitMetric,methodology,methodologyVersion,validationApproach,validationDate,projectTag,estimatedAnnualAverageEmissionReduction,projectLocations,qualifications,vintages,coBenefits,relatedProjects +5c960ac1-a180-45a4-9850-be177e26d2fb,c5067a60-e329-4510-991c-b302fd00ec8d,c9d147e2-bc07-4e68-a76d-43424fa8cd4e,Eimbee,Zoomcast,http://dailymotion.com/ligula/suspendisse/ornare/consequat/lectus/in.jpg?aliquam=consequat&lacus=nulla&morbi=nisl&quis=nunc&tortor=nisl&id=duis&nulla=bibendum&ultrices=felis&aliquet=sed&maecenas=interdum&leo=venenatis&odio=turpis&condimentum=enim&id=blandit&luctus=mi&nec=in&molestie=porttitor&sed=pede&justo=justo&pellentesque=eu&viverra=massa&pede=donec&ac=dapibus&diam=duis&cras=at&pellentesque=velit&volutpat=eu&dui=est&maecenas=congue&tristique=elementum&est=in&et=hac&tempus=habitasse&semper=platea&est=dictumst&quam=morbi&pharetra=vestibulum&magna=velit&ac=id&consequat=pretium&metus=iaculis&sapien=diam&ut=erat&nunc=fermentum&vestibulum=justo&ante=nec&ipsum=condimentum,Cogibox,Viva,Topicshots,0,Shuffletag,"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",1/19/2022,Fuscia,Quatz,43,He waited for the stop sign to turn to a go sign.,1/19/2022,Neque,120,United States,https://qualification.link/1,"3d5a8ed2-e5a7-4275-a36e-3456812e39b7,57c1859d-6aa4-4c57-9dfb-6438e0d4653e",TEST_COBENEFIT_4,394e319e-a4d2-4ad8-a4b3-0d5b660dd8ec +7703e6be-1781-4322-9a9c-502ca0dca29b,c5067a60-e329-4510-991c-b302fd00ec8d,c9d147e2-bc07-4e68-a76d-43424fa8cd4e,Eimbee,Zoomcast,http://dailymotion.com/ligula/suspendisse/ornare/consequat/lectus/in.jpg?aliquam=consequat&lacus=nulla&morbi=nisl&quis=nunc&tortor=nisl&id=duis&nulla=bibendum&ultrices=felis&aliquet=sed&maecenas=interdum&leo=venenatis&odio=turpis&condimentum=enim&id=blandit&luctus=mi&nec=in&molestie=porttitor&sed=pede&justo=justo&pellentesque=eu&viverra=massa&pede=donec&ac=dapibus&diam=duis&cras=at&pellentesque=velit&volutpat=eu&dui=est&maecenas=congue&tristique=elementum&est=in&et=hac&tempus=habitasse&semper=platea&est=dictumst&quam=morbi&pharetra=vestibulum&magna=velit&ac=id&consequat=pretium&metus=iaculis&sapien=diam&ut=erat&nunc=fermentum&vestibulum=justo&ante=nec&ipsum=condimentum,Cogibox,Seven,Topicshots,0,Shuffletag,"I know many children ask for a pony, but I wanted a bicycle with rockets strapped to it.",1/19/2022,Fuscia,Quatz,43,He waited for the stop sign to turn to a go sign.,1/19/2022,Neque,120,United States,https://qualification.link/1,"3d5a8ed2-e5a7-4275-a36e-3456812e39b7,57c1859d-6aa4-4c57-9dfb-6438e0d4653e",TEST_COBENEFIT_4,394e319e-a4d2-4ad8-a4b3-0d5b660dd8ec +04582672-47a9-411b-896f-3d45974e360e,c5067a60-e329-4510-991c-b302fd00ec8d,c9d147e2-bc07-4e68-a76d-43424fa8cd4e,Eimbee,Zoomcast,http://dailymotion.com/ligula/suspendisse/ornare/consequat/lectus/in.jpg?aliquam=consequat&lacus=nulla&morbi=nisl&quis=nunc&tortor=nisl&id=duis&nulla=bibendum&ultrices=felis&aliquet=sed&maecenas=interdum&leo=venenatis&odio=turpis&condimentum=enim&id=blandit&luctus=mi&nec=in&molestie=porttitor&sed=pede&justo=justo&pellentesque=eu&viverra=massa&pede=donec&ac=dapibus&diam=duis&cras=at&pellentesque=velit&volutpat=eu&dui=est&maecenas=congue&tristique=elementum&est=in&et=hac&tempus=habitasse&semper=platea&est=dictumst&quam=morbi&pharetra=vestibulum&magna=velit&ac=id&consequat=pretium&metus=iaculis&sapien=diam&ut=erat&nunc=fermentum&vestibulum=justo&ante=nec&ipsum=condimentum,Cogibox,Viva,Topicshots,0,Shuffletag,"I know many children ask for a pony, but I wanted a bicycle with rockets strapped to it.",1/22/2022,Fuscia,Quatz,43,He waited for the stop sign to turn to a go sign.,1/19/2022,Neque,120,United States,https://qualification.link/1,"3d5a8ed2-e5a7-4275-a36e-3456812e39b7,57c1859d-6aa4-4c57-9dfb-6438e0d4653e",TEST_COBENEFIT_4,394e319e-a4d2-4ad8-a4b3-0d5b660dd8ec diff --git a/package-lock.json b/package-lock.json index aa521b83..25a5a4e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "joi": "^17.5.0", "lodash": "^4.17.21", "mysql2": "^2.3.3", + "request-promise": "^4.2.6", "rxjs": "^7.5.1", "sequelize": "^6.12.0-alpha.1", "sequelize-mock": "^0.10.2", @@ -13036,6 +13037,50 @@ "node": ">= 6" } }, + "node_modules/request-promise": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz", + "integrity": "sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==", + "deprecated": "request-promise has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142", + "dependencies": { + "bluebird": "^3.5.0", + "request-promise-core": "1.1.4", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "request": "^2.34" + } + }, + "node_modules/request-promise-core": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", + "dependencies": { + "lodash": "^4.17.19" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "request": "^2.34" + } + }, + "node_modules/request-promise/node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/request/node_modules/form-data": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", @@ -13963,6 +14008,14 @@ "node": ">= 0.6" } }, + "node_modules/stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/streamsearch": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", @@ -25374,6 +25427,36 @@ } } }, + "request-promise": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz", + "integrity": "sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==", + "requires": { + "bluebird": "^3.5.0", + "request-promise-core": "1.1.4", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + }, + "dependencies": { + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + } + } + }, + "request-promise-core": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", + "requires": { + "lodash": "^4.17.19" + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -26067,6 +26150,11 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" + }, "streamsearch": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", diff --git a/package.json b/package.json index 1a6140c0..96fde78b 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "joi": "^17.5.0", "lodash": "^4.17.21", "mysql2": "^2.3.3", + "request-promise": "^4.2.6", "rxjs": "^7.5.1", "sequelize": "^6.12.0-alpha.1", "sequelize-mock": "^0.10.2", diff --git a/src/controllers/organization.controller.js b/src/controllers/organization.controller.js index 9f030b27..c7bf2ce2 100644 --- a/src/controllers/organization.controller.js +++ b/src/controllers/organization.controller.js @@ -1,5 +1,13 @@ import { Organization } from '../models/organizations'; - +import { updateOrganization } from '../fullnode/dataLayerService'; export const findAll = async (req, res) => { return res.json(await Organization.getOrgsMap()); }; + +export const create = async (req, res) => { + const { name, icon, website } = req.body; + return res.json({ + message: 'New organization created successfully.', + orgId: await updateOrganization(name, icon, website), + }); +}; diff --git a/src/controllers/project.controller.js b/src/controllers/project.controller.js index 8338713f..858dde30 100644 --- a/src/controllers/project.controller.js +++ b/src/controllers/project.controller.js @@ -23,31 +23,34 @@ import { assertOrgIsHomeOrg, assertProjectRecordExists, assertCsvFileInRequest, + assertHomeOrgExists, } from '../utils/data-assertions'; import { createProjectRecordsFromCsv } from '../utils/csv-utils'; export const create = async (req, res) => { - const newRecord = _.cloneDeep(req.body); - // When creating new projects assign a uuid to is so - // multiple organizations will always have unique ids - const uuid = uuidv4(); + try { + await assertHomeOrgExists(); - newRecord.warehouseProjectId = uuid; + const newRecord = _.cloneDeep(req.body); + // When creating new projects assign a uuid to is so + // multiple organizations will always have unique ids + const uuid = uuidv4(); - // All new projects are assigned to the home orgUid - const orgUid = _.head(Object.keys(await Organization.getHomeOrg())); - newRecord.orgUid = orgUid; + newRecord.warehouseProjectId = uuid; - // The new project is getting created in this registry - newRecord.currentRegistry = orgUid; + // All new projects are assigned to the home orgUid + const orgUid = _.head(Object.keys(await Organization.getHomeOrg())); + newRecord.orgUid = orgUid; - // Unless we are overriding, a new project originates in this org - if (!newRecord.registryOfOrigin) { - newRecord.registryOfOrigin = orgUid; - } + // The new project is getting created in this registry + newRecord.currentRegistry = orgUid; + + // Unless we are overriding, a new project originates in this org + if (!newRecord.registryOfOrigin) { + newRecord.registryOfOrigin = orgUid; + } - try { await Staging.create({ uuid, action: 'INSERT', @@ -131,6 +134,8 @@ export const findOne = async (req, res) => { export const update = async (req, res) => { try { + await assertHomeOrgExists(); + const originalRecord = await assertProjectRecordExists( req.body.warehouseProjectId, ); @@ -165,6 +170,8 @@ export const update = async (req, res) => { export const destroy = async (req, res) => { try { + await assertHomeOrgExists(); + const originalRecord = await assertProjectRecordExists( req.body.warehouseProjectId, ); @@ -192,6 +199,8 @@ export const destroy = async (req, res) => { export const batchUpload = async (req, res) => { try { + await assertHomeOrgExists(); + const csvFile = assertCsvFileInRequest(req); await createProjectRecordsFromCsv(csvFile); diff --git a/src/controllers/staging.controller.js b/src/controllers/staging.controller.js index c303ecaf..f078240b 100644 --- a/src/controllers/staging.controller.js +++ b/src/controllers/staging.controller.js @@ -176,3 +176,135 @@ export const clean = async (req, res) => { }); } }; + +export const commitV2 = async (req, res) => { + try { + const queryResponses = await Staging.findAll(); + + const changeList = []; + + await Promise.all( + queryResponses.map(async (queryResponse) => { + const stagingRecord = queryResponse.dataValues; + + const { + id: stagingRecordId, + uuid, + table, + action, + commited, + data: rawData, + } = stagingRecord; + let data = JSON.parse(rawData); + + if (table === 'Projects' && !commited) { + const customAssertionMessage = `The project record for the warehouseProjectId: ${uuid} does not exist. Please remove ${uuid} from the staging table and try to commit again.`; + const projectRecord = _.omit(data, 'qualifications', 'vintages'); + // const qualificationsRecords = data.qualifications; + // const vintageRecords = data.vintages; + + console.log('!@@'); + + switch (action) { + case 'INSERT': + data.warehouseProjectId = uuid; + + changeList.push([ + { + action: 'delete', + key: new Buffer(`project_${uuid}`).toString('hex'), + }, + { + action: 'insert', + key: new Buffer(`project_${uuid}`).toString('hex'), + value: new Buffer(JSON.stringify(projectRecord)).toString( + 'hex', + ), + }, + ]); + break; + case 'UPDATE': + await assertProjectRecordExists(uuid, customAssertionMessage); + changeList.push([ + { + action: 'delete', + key: new Buffer(`project_${uuid}`).toString('hex'), + }, + { + action: 'insert', + key: new Buffer(`project_${uuid}`).toString('hex'), + value: new Buffer(JSON.stringify(data)).toString('hex'), + }, + ]); + break; + case 'DELETE': + await assertProjectRecordExists(uuid, customAssertionMessage); + changeList.push([ + { + action: 'delete', + key: new Buffer(`project_${uuid}`).toString('hex'), + }, + ]); + break; + } + } else if (table === 'Units' && !commited) { + const customAssertionMessage = `The unit record for the warehouseUnitId: ${uuid} does not exist. Please remove ${uuid} from the staging table and try to commit again.`; + const unitRecord = _.omit(data, 'qualifications', 'vintage'); + switch (action) { + case 'INSERT': + changeList.push({ + action: 'delete', + key: new Buffer(`unit_${uuid}`).toString('hex'), + }); + changeList.push({ + action: 'insert', + key: new Buffer(`unit_${uuid}`).toString('hex'), + value: new Buffer(JSON.stringify(unitRecord)).toString('hex'), + }); + + break; + case 'UPDATE': + await assertUnitRecordExists(uuid, customAssertionMessage); + changeList.push([ + { + action: 'delete', + key: new Buffer(`unit_${uuid}`).toString('hex'), + }, + { + action: 'insert', + key: new Buffer(`unit_${uuid}`).toString('hex'), + value: new Buffer(JSON.stringify(unitRecord)).toString('hex'), + }, + ]); + break; + case 'DELETE': + await assertUnitRecordExists(uuid, customAssertionMessage); + changeList.push([ + { + action: 'delete', + key: new Buffer(`unit_${uuid}`).toString('hex'), + }, + ]); + break; + } + } + + // set the commited flag to true + await Staging.update( + { commited: true }, + { where: { id: stagingRecordId } }, + ); + }), + ); + + console.log(changeList); + await fullNode.pushChangeListToRegistryTable('units', changeList); + + res.json({ message: 'Staging Table committed to full node' }); + } catch (error) { + res.status(400).json({ + message: 'Error commiting staging table', + error: error.message, + }); + } +}; diff --git a/src/controllers/units.controller.js b/src/controllers/units.controller.js index f77bc59c..55e20b2f 100644 --- a/src/controllers/units.controller.js +++ b/src/controllers/units.controller.js @@ -18,12 +18,15 @@ import { assertSumOfSplitUnitsIsValid, assertCsvFileInRequest, assertOrgUidIsValid, + assertHomeOrgExists, } from '../utils/data-assertions'; import { createUnitRecordsFromCsv } from '../utils/csv-utils'; export const create = async (req, res) => { try { + await assertHomeOrgExists(); + const newRecord = _.cloneDeep(req.body); // When creating new unitd assign a uuid to is so @@ -149,6 +152,8 @@ export const findOne = async (req, res) => { export const update = async (req, res) => { try { + await assertHomeOrgExists(); + const originalRecord = await assertUnitRecordExists( req.body.warehouseUnitId, ); @@ -187,6 +192,8 @@ export const update = async (req, res) => { export const destroy = async (req, res) => { try { + await assertHomeOrgExists(); + const originalRecord = await assertUnitRecordExists( req.body.warehouseUnitId, ); @@ -213,6 +220,8 @@ export const destroy = async (req, res) => { export const split = async (req, res) => { try { + await assertHomeOrgExists(); + const originalRecord = await assertUnitRecordExists( req.body.warehouseUnitId, ); @@ -277,6 +286,8 @@ export const split = async (req, res) => { export const batchUpload = async (req, res) => { try { + await assertHomeOrgExists(); + const csvFile = assertCsvFileInRequest(req); await createUnitRecordsFromCsv(csvFile); diff --git a/src/controllers/vintage.controller.js b/src/controllers/vintage.controller.js index 7e9a30c8..1e44bad5 100644 --- a/src/controllers/vintage.controller.js +++ b/src/controllers/vintage.controller.js @@ -1,11 +1,21 @@ import { Vintage, Organization } from '../models'; +import { assertHomeOrgExists } from '../utils/data-assertions'; + export const findAll = async (req, res) => { - const homeOrg = await Organization.getHomeOrg(); - console.log({ orgUid: Object.keys(homeOrg)[0] }); - return res.json( - await Vintage.findAll({ - where: { orgUid: Object.keys(homeOrg)[0] }, - }), - ); + try { + await assertHomeOrgExists(); + const homeOrg = await Organization.getHomeOrg(); + console.log({ orgUid: Object.keys(homeOrg)[0] }); + return res.json( + await Vintage.findAll({ + where: { orgUid: Object.keys(homeOrg)[0] }, + }), + ); + } catch (error) { + res.status(400).json({ + message: 'Can not retreive vintages', + error: error.message, + }); + } }; diff --git a/src/fullnode/dataLayerService.js b/src/fullnode/dataLayerService.js new file mode 100644 index 00000000..35156490 --- /dev/null +++ b/src/fullnode/dataLayerService.js @@ -0,0 +1,162 @@ +import { Meta } from '../models'; +import * as dataLayer from './persistance'; +import * as simulator from './simulatorV2'; + +const strToHex = (str) => { + console.log('str', str); + return new Buffer(str).toString('hex'); +}; + +const createChangeObject = (type, key, value) => { + console.log(type, key, value); + return { action: type, key: strToHex(key), value: strToHex(value) }; +}; + +const ensureDataLayerStore = async (metaKey) => { + const storeMeta = await Meta.findOne({ + where: { metaKey }, + }); + + console.log('@@@', storeMeta); + + if (!storeMeta) { + let storeId; + if (process.env.USE_SIMULATOR === 'true') { + storeId = await simulator.createDataLayerStore(); + } else { + storeId = await dataLayer.createDataLayerStore(); + } + + console.log({ [metaKey]: storeId }); + + await Meta.create({ [metaKey]: storeId }); + return storeId; + } + + return storeMeta.metaValue; +}; + +const ensureRegistryStore = async (orgUid) => { + const storeId = await ensureDataLayerStore('registryId'); + const changeList = [createChangeObject('insert', 'registryId', storeId)]; + + console.log('#####orgUid', orgUid, changeList); + + let registryId; + if (process.env.USE_SIMULATOR === 'true') { + registryId = await simulator.pushChangeListToDataLayer(orgUid, changeList); + } else { + registryId = await dataLayer.pushChangeListToDataLayer(orgUid, changeList); + } + await Meta.create({ registryId }); + return registryId; +}; + +const ensureRegistryTableStore = async (tableName) => { + const orgUid = await ensureOrganizationStore(); + const registryId = await ensureRegistryStore(orgUid); + const metaKey = `${tableName}StoreId`; + const storeId = await ensureDataLayerStore(metaKey); + const changeList = [createChangeObject('insert', metaKey, storeId)]; + + let registryTableStoreId; + if (process.env.USE_SIMULATOR === 'true') { + registryTableStoreId = await simulator.pushChangeListToDataLayer( + registryId, + changeList, + ); + } else { + registryTableStoreId = await dataLayer.pushChangeListToDataLayer( + registryId, + changeList, + ); + } + + await Meta.create({ [metaKey]: registryTableStoreId }); + + console.log('3############', registryTableStoreId); + return registryTableStoreId; +}; + +const ensureOrganizationStore = async () => { + const metaKey = 'organizationId'; + const storeMeta = await Meta.findOne({ + where: { metaKey }, + }); + + if (!storeMeta) { + let storeId; + + if (process.env.USE_SIMULATOR === 'true') { + storeId = await simulator.createDataLayerStore(); + } else { + storeId = await dataLayer.createDataLayerStore(); + } + + await Meta.upsert({ metaKey: 'organizationId', metaValue: storeId }); + return storeId; + } + + return storeMeta.metaValue; +}; + +export const pushChangeListToRegistryTable = async (tableName, changeList) => { + const storeId = await ensureRegistryTableStore(tableName); + + console.log('########', storeId); + + if (storeId) { + if (process.env.USE_SIMULATOR === 'true') { + return simulator.pushChangeListToDataLayer(storeId, changeList); + } else { + return dataLayer.pushChangeListToDataLayer(storeId, changeList); + } + } + + throw new Error('Could not create datalayer store'); +}; + +export const getRegistryTableData = async (tableName) => { + const storeId = await ensureDataLayerStore(tableName); + + if (process.env.USE_SIMULATOR === 'true') { + return simulator.getStoreData(storeId); + } else { + return dataLayer.getStoreData(storeId); + } +}; + +export const updateOrganization = async (orgName, orgIconUrl, orgWebSite) => { + const orgUid = await ensureOrganizationStore(); + + const changeList = []; + const metaUpdateList = []; + if (orgName) { + changeList.push[createChangeObject('insert', 'name', orgName)]; + metaUpdateList.push({ metaKey: 'organizationName', metaValue: orgName }); + } + + if (orgIconUrl) { + changeList.push[createChangeObject('insert', 'iconUrl', orgIconUrl)]; + metaUpdateList.push({ + metaKey: 'organizationIconUrl', + metaValue: orgIconUrl, + }); + } + + if (orgWebSite) { + changeList.push[createChangeObject('insert', 'website', orgWebSite)]; + metaUpdateList.push({ + metaKey: 'organizationWebsite', + metaValue: orgWebSite, + }); + } + + await Meta.bulkCreate(metaUpdateList); + + if (process.env.USE_SIMULATOR === 'true') { + return simulator.pushChangeListToDataLayer(orgUid, changeList); + } else { + return dataLayer.pushChangeListToDataLayer(orgUid, changeList); + } +}; diff --git a/src/fullnode/datalayer.js b/src/fullnode/datalayer.js deleted file mode 100644 index 41b377c6..00000000 --- a/src/fullnode/datalayer.js +++ /dev/null @@ -1,47 +0,0 @@ -import fs from 'fs'; -import path from 'path'; -import request from 'request'; - -process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0; - -const certFile = path.resolve( - `${process.env.CHIA_ROOT}/config/ssl/data_layer/private_data_layer.crt`, -); -const keyFile = path.resolve( - `${process.env.CHIA_ROOT}/config/ssl/data_layer/private_data_layer.key`, -); - -const rpcUrl = process.env.DATALAYER_URL; - -const baseOptions = { - method: 'POST', - cert: fs.readFileSync(certFile), - key: fs.readFileSync(keyFile), -}; - -export const pushChangeListToDatalayer = (changeList) => { - return new Promise((resolve, reject) => { - const options = { - url: `${rpcUrl}/update_data_store`, - body: JSON.stringify({ - changelist: changeList, - id: 'c19cfd5a1f0a221976debcd1206daca0a07bf5e949949c2f30488562870a2fff', - }), - }; - - console.log(changeList); - - request( - Object.assign({}, baseOptions, options), - function (error, response) { - if (error) { - console.log('!!!!!!'); - reject(error); - return; - } - console.log(response.body); - resolve(response); - }, - ); - }); -}; diff --git a/src/fullnode/index.js b/src/fullnode/index.js index 3cc3e43f..5b1d0cd6 100644 --- a/src/fullnode/index.js +++ b/src/fullnode/index.js @@ -1 +1,2 @@ export * from './dispatcher'; +export * from './dataLayerService'; diff --git a/src/fullnode/persistance.js b/src/fullnode/persistance.js new file mode 100644 index 00000000..9e52b6dd --- /dev/null +++ b/src/fullnode/persistance.js @@ -0,0 +1,72 @@ +import fs from 'fs'; +import path from 'path'; +import request from 'request-promise'; + +process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0; + +const rpcUrl = process.env.DATALAYER_URL; + +const certFile = path.resolve( + `${process.env.CHIA_ROOT}/config/ssl/data_layer/private_data_layer.crt`, +); +const keyFile = path.resolve( + `${process.env.CHIA_ROOT}/config/ssl/data_layer/private_data_layer.key`, +); + +const baseOptions = { + method: 'POST', + cert: fs.readFileSync(certFile), + key: fs.readFileSync(keyFile), +}; + +export const createDataLayerStore = async () => { + const options = { + url: `${rpcUrl}/create_data_store`, + body: JSON.stringify({}), + }; + + const response = await request(Object.assign({}, baseOptions, options)); + + if (response.body.id) { + return response.body.id; + } + + throw new Error('Error creating new datalayer store'); +}; + +export const pushChangeListToDataLayer = async (storeId, changeList) => { + const options = { + url: `${rpcUrl}/update_data_store`, + body: JSON.stringify({ + changelist: changeList, + id: storeId, + }), + }; + + const response = request(Object.assign({}, baseOptions, options)); + + if (response.body) { + return response.body; + } + + throw new Error('Error updating datalayer store'); +}; + +export const getStoreData = async (storeId) => { + if (storeId) { + const options = { + url: `${rpcUrl}/get_keys_values`, + body: JSON.stringify({ + id: storeId, + }), + }; + + const response = request(Object.assign({}, baseOptions, options)); + + if (response.body && response.body.keys_values) { + return response.body.keys_values; + } + } + + return new Error('Error getting datalayer store data'); +}; diff --git a/src/fullnode/simulatorV2.js b/src/fullnode/simulatorV2.js new file mode 100644 index 00000000..9b1477a4 --- /dev/null +++ b/src/fullnode/simulatorV2.js @@ -0,0 +1,54 @@ +import { uuid as uuidv4 } from 'uuidv4'; +import { Meta } from '../models'; +import { Sequelize } from 'sequelize'; + +const Op = Sequelize.Op; + +export const createDataLayerStore = async () => { + return uuidv4(); +}; + +export const pushChangeListToDataLayer = (storeId, changeList) => { + console.log('!!!!!', storeId, changeList); + return Promise.all( + changeList.map(async (change) => { + if (change.action === 'insert') { + await Meta.create({ + metaKey: `${storeId}_${change.key}`, + metaValue: change.value, + }); + } else if (change.action === 'delete') { + await Meta.destroy({ + where: { metaKey: `simulator_${storeId}_${change.key}` }, + }); + } + }), + ); +}; + +export const getStoreData = async (storeId) => { + if (storeId) { + const results = await await Meta.findAll({ + where: { + metaKey: { [Op.like]: `simulator_${storeId}%` }, + }, + }); + + // return the store data in a form that mirrors that datalayer response + return { + keys_values: results.map((result) => { + const simulatedResult = result; + simulatedResult.hash = result.metaValue.split('').reduce((a, b) => { + a = (a << 5) - a + b.charCodeAt(0); + return a & a; + }, 0); + simulatedResult.atom = null; + simulatedResult.key = result.metaKey; + simulatedResult.value = result.metaValue; + return simulatedResult; + }), + }; + } + + return new Error('Error getting datalayer store data'); +}; diff --git a/src/models/meta/meta.model.js b/src/models/meta/meta.model.js index 0123f366..fc478237 100644 --- a/src/models/meta/meta.model.js +++ b/src/models/meta/meta.model.js @@ -11,6 +11,9 @@ class Meta extends Model {} Meta.init(ModelTypes, { sequelize, modelName: 'meta', + timestamps: false, + createdAt: false, + updatedAt: false, }); export { Meta }; diff --git a/src/models/meta/meta.modeltypes.cjs b/src/models/meta/meta.modeltypes.cjs index 28e9424a..1080b279 100644 --- a/src/models/meta/meta.modeltypes.cjs +++ b/src/models/meta/meta.modeltypes.cjs @@ -6,9 +6,9 @@ module.exports = { primaryKey: true, autoIncrement: true, }, - meta_key: { + metaKey: { type: Sequelize.STRING, unique: true, }, - meta_value: Sequelize.STRING, + metaValue: Sequelize.STRING, }; diff --git a/src/models/organizations/organizations.model.js b/src/models/organizations/organizations.model.js index 3c835b8a..17cf72c7 100644 --- a/src/models/organizations/organizations.model.js +++ b/src/models/organizations/organizations.model.js @@ -3,18 +3,39 @@ import Sequelize from 'sequelize'; const { Model } = Sequelize; import { sequelize } from '../database'; +import { Meta } from '../../models'; import ModelTypes from './organizations.modeltypes.cjs'; class Organization extends Model { static async getHomeOrg() { - return { - 'f1c54511-865e-4611-976c-7c3c1f704662': { - name: 'Chia Demo Organization', - icon: 'https://climate-warehouse.s3.us-west-2.amazonaws.com/public/orgs/me.svg', - writeAccess: true, - }, - }; + const organizationRecord = await Meta.findOne({ + where: { metaKey: 'organizationId' }, + }); + const organizationNameRecord = await Meta.findOne({ + where: { metaKey: 'organizationName' }, + }); + const organizationIconRecord = await Meta.findOne({ + where: { metaKey: 'organizationIconUrl' }, + }); + + if (organizationRecord) { + let homeOrg = { [organizationRecord.metaValue]: { writeAccess: true } }; + + if (organizationNameRecord) { + homeOrg[organizationRecord.metaValue].name = + organizationNameRecord.metaValue; + } + + if (organizationIconRecord) { + homeOrg[organizationRecord.metaValue].icon = + organizationIconRecord.metaValue; + } + + return homeOrg; + } + + return undefined; } static async getOrgsMap() { diff --git a/src/models/vintages/vintages.stub.json b/src/models/vintages/vintages.stub.json index 17b9fd2a..5e418553 100644 --- a/src/models/vintages/vintages.stub.json +++ b/src/models/vintages/vintages.stub.json @@ -2,9 +2,9 @@ { "id": "a6745831-5d5e-45ed-b9fe-fd6aa129df25", "orgUid": "f1c54511-865e-4611-976c-7c3c1f704662", - "startDate": "11/21/22", - "endDate": "12/2/22", - "verificationDate": "11/19/22", + "startDate": "2021-01-18", + "endDate": "2022-01-18", + "verificationDate": "2022-01-18 ", "verificationBody": "This is verified", "warehouseProjectId": "81e05bfa-e93f-458f-b907-96bf170e52cd", "createdAt": "2022-01-18 00:05:45.701 +00:00", @@ -13,9 +13,9 @@ { "id": "3d5a8ed2-e5a7-4275-a36e-3456812e39b7", "orgUid": "f1c54511-865e-4611-976c-7c3c1f704662", - "startDate": "3/2/22", - "endDate": "5/5/22", - "verificationDate": "1/19/22", + "startDate": "2021-01-18", + "endDate": "2022-01-18", + "verificationDate": "2022-01-18", "verificationBody": "This is verified", "warehouseProjectId": "81e05bfa-e93f-458f-b907-96bf170e52cd", "createdAt": "2022-01-18 00:05:45.701 +00:00", @@ -24,9 +24,9 @@ { "id": "57c1859d-6aa4-4c57-9dfb-6438e0d4653e", "orgUid": "f1c54511-865e-4611-976c-7c3c1f704662", - "startDate": "4/14/22", - "endDate": "7/25/22", - "verificationDate": "3/8/22", + "startDate": "2021-01-18", + "endDate": "2022-01-18", + "verificationDate": "2022-01-18", "verificationBody": "This is verified", "warehouseProjectId": "81e05bfa-e93f-458f-b907-96bf170e52cd", "createdAt": "2022-01-18 00:05:45.701 +00:00", @@ -35,9 +35,9 @@ { "id": "74887b22-da3b-4c2b-b945-670319193cdd", "orgUid": "f1c54511-865e-4611-976c-7c3c1f704662", - "startDate": "7/23/22", - "endDate": "9/12/22", - "verificationDate": "5/4/22", + "startDate": "2021-01-18", + "endDate": "2022-01-18", + "verificationDate": "2022-01-18", "verificationBody": "This is verified", "warehouseProjectId": "81e05bfa-e93f-458f-b907-96bf170e52cd", "createdAt": "2022-01-18 00:05:45.701 +00:00", @@ -46,9 +46,9 @@ { "id": "7f7f23a5-3e1a-43b4-82d8-b4156b158f88", "orgUid": "f1c54511-865e-4611-976c-7c3c1f704662", - "startDate": "9/13/22", - "endDate": "11/21/22", - "verificationDate": "8/22/22", + "startDate": "2021-01-18", + "endDate": "2022-01-18", + "verificationDate": "2022-01-18", "verificationBody": "This is verified", "warehouseProjectId": "81e05bfa-e93f-458f-b907-96bf170e52cd", "createdAt": "2022-01-18 00:05:45.701 +00:00", diff --git a/src/routes/v1/resources/organization.js b/src/routes/v1/resources/organization.js index 6321a453..568112ca 100644 --- a/src/routes/v1/resources/organization.js +++ b/src/routes/v1/resources/organization.js @@ -10,4 +10,8 @@ OrganizationRouter.get('/', (req, res) => { return OrganizationController.findAll(req, res); }); +OrganizationRouter.post('/', (req, res) => { + return OrganizationController.create(req, res); +}); + export { OrganizationRouter }; diff --git a/src/routes/v1/resources/staging.js b/src/routes/v1/resources/staging.js index 29d04581..154df971 100644 --- a/src/routes/v1/resources/staging.js +++ b/src/routes/v1/resources/staging.js @@ -19,7 +19,7 @@ StagingRouter.delete( StagingController.destroy, ); -StagingRouter.post('/commit', StagingController.commit); +StagingRouter.post('/commit', StagingController.commitV2); // Empty entire stagin table StagingRouter.delete('/clean', StagingController.clean); diff --git a/src/utils/csv-utils.js b/src/utils/csv-utils.js index a69b0f4d..0a0fd26f 100644 --- a/src/utils/csv-utils.js +++ b/src/utils/csv-utils.js @@ -67,7 +67,9 @@ export const createUnitRecordsFromCsv = (csvFile) => { }) .on('done', async () => { if (recordsToCreate.length) { - await Staging.bulkCreate(recordsToCreate); + await Staging.bulkCreate(recordsToCreate, { + updateOnDuplicate: ['warehouseUnitId'], + }); resolve(); } else { @@ -109,7 +111,7 @@ export const createProjectRecordsFromCsv = (csvFile) => { } const stagedData = { - uuid: newRecord.warehouseUnitId, + uuid: newRecord.warehouseProjectId, action: action, table: Project.stagingTableName, data: JSON.stringify([newRecord]), @@ -122,7 +124,9 @@ export const createProjectRecordsFromCsv = (csvFile) => { }) .on('done', async () => { if (recordsToCreate.length) { - await Staging.bulkCreate(recordsToCreate); + await Staging.bulkCreate(recordsToCreate, { + updateOnDuplicate: ['warehouseProjectId'], + }); resolve(); } else { diff --git a/src/utils/data-assertions.js b/src/utils/data-assertions.js index 3cc1ef8d..ce720c12 100644 --- a/src/utils/data-assertions.js +++ b/src/utils/data-assertions.js @@ -5,6 +5,17 @@ import _ from 'lodash'; import { Organization, Unit, Project, Staging } from '../models'; import { transformSerialNumberBlock } from '../utils/helpers'; +export const assertHomeOrgExists = async () => { + const homeOrg = await Organization.getHomeOrg(); + if (!homeOrg) { + throw new Error( + `No Home organization found, please create an organization to write data`, + ); + } + + return homeOrg; +}; + export const assertOrgUidIsValid = async (orgUid, fieldName) => { const orgMap = await Organization.getOrgsMap(); if (!orgMap[orgUid]) { diff --git a/src/validations/units.validations.js b/src/validations/units.validations.js index b8ab3dff..ea71c4bf 100644 --- a/src/validations/units.validations.js +++ b/src/validations/units.validations.js @@ -51,7 +51,7 @@ const unitsBaseSchema = { .valid('Commited', 'Not Required', 'Unknown') .required(), correspondingAdjustmentStatus: Joi.string() - .valid('Not Started', 'Pending') + .valid('Unknown', 'Not Started', 'Pending') .required(), vintages: Joi.alternatives() .try(newVintageScheme, existingVintageSchema)