Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev sync 9 #37

Merged
merged 44 commits into from
Feb 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
293e3f7
Merge pull request #26 from undp/develop
mbelinsky Feb 7, 2023
107691a
Create TOR National Implementation
timschloe Feb 8, 2023
0a1cb64
Rename TOR National Implementation to TOR National Implementation.md
timschloe Feb 8, 2023
0ecdd35
Update TOR National Implementation.md
timschloe Feb 8, 2023
a50ad40
Merge pull request #30 from undp/develop
mbelinsky Feb 10, 2023
d01a322
Update README.md
mbelinsky Feb 10, 2023
6953d78
Update README.md
mbelinsky Feb 10, 2023
8f1e680
Update TOR National Implementation.md
reinaotsuka Feb 13, 2023
accb30d
Update TOR National Implementation.md
reinaotsuka Feb 14, 2023
e49e0fd
Update README.md
mbelinsky Feb 15, 2023
2149916
Revert "add code spliting"
palindaa Feb 23, 2023
85e0b65
Merge pull request #349 from xeptagondev/revert-348-Bug/carbon-77-con…
palindaa Feb 23, 2023
5b74159
Merge pull request #350 from xeptagondev/dev_fix_7
palindaa Feb 23, 2023
a77fa88
Fixed the pie charts legend items alignment issue
YathurshanT Feb 24, 2023
de485ba
Merge branch 'develop' of https://github.com/xeptagondev/undp-carbon-…
YathurshanT Feb 24, 2023
020d761
dashboard front end changes
YathurshanT Feb 24, 2023
73870ee
Merge pull request #351 from xeptagondev/dashboard-backend
palindaa Feb 24, 2023
ee4b6de
hide the lib info div in the maps
YathurshanT Feb 24, 2023
13359de
Merge branch 'develop' of https://github.com/xeptagondev/undp-carbon-…
YathurshanT Feb 24, 2023
86c2173
changes on height and width of images,contrast ratio of home button …
Uvinduxeptagon Feb 24, 2023
e0961e4
minor mapbox css changes
YathurshanT Feb 24, 2023
a85bb0e
Merge pull request #352 from xeptagondev/dashboard-backend
palindaa Feb 24, 2023
856b7e0
Merge pull request #353 from xeptagondev/homepage-ui
palindaa Feb 24, 2023
7c217f5
toolTipTextsChanges
YathurshanT Feb 24, 2023
9e76493
Merge branch 'develop' of https://github.com/xeptagondev/undp-carbon-…
YathurshanT Feb 24, 2023
deac567
Merge pull request #354 from xeptagondev/dashboard-backend
palindaa Feb 24, 2023
0d0a92b
toolTip changes
YathurshanT Feb 25, 2023
5490b58
Merge branch 'develop' of https://github.com/xeptagondev/undp-carbon-…
YathurshanT Feb 25, 2023
a11b6b5
Merge pull request #355 from xeptagondev/dashboard-backend
palindaa Feb 25, 2023
dbaba99
chart_option value format changes
YathurshanT Feb 27, 2023
fa1a544
Merge branch 'develop' of https://github.com/xeptagondev/undp-carbon-…
YathurshanT Feb 27, 2023
10beb5c
Merge pull request #356 from xeptagondev/dashboard-backend
palindaa Feb 27, 2023
a4e5637
fixed path decimal points issues in dashboard pie charts
YathurshanT Feb 27, 2023
073755f
Deleted unwanted error console in dashboard
YathurshanT Feb 27, 2023
b24d49d
Merge branch 'develop' of https://github.com/xeptagondev/undp-carbon-…
YathurshanT Feb 27, 2023
1b31506
deleted the unwanted imports in dashboard
YathurshanT Feb 27, 2023
cc25efc
Merge pull request #357 from xeptagondev/dashboard-backend
dhanushkaxep Feb 27, 2023
5baf50b
Update documentation
palindaa Feb 27, 2023
85f2880
issue fixes
dhanushkaxep Feb 27, 2023
cbf593a
Merge branch 'develop' into doc_update
palindaa Feb 27, 2023
0ae13b7
Merge pull request #358 from xeptagondev/doc_update
palindaa Feb 27, 2023
6ccbb97
Merge pull request #359 from xeptagondev/feat/carbon-91-organisation-…
palindaa Feb 27, 2023
da3536c
Update the ledger image
palindaa Feb 27, 2023
e05c200
Merge pull request #360 from xeptagondev/doc_update
palindaa Feb 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 110 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@

## Index
* [About](#about)
* [Standards](#standards)
* [Architecture](#architecture)
* [Project Structure](#structure)
* [Run Services Locally](#local)
* [Run Services on Cloud](#cloud)
* [User Onboarding](#user)
* [Web Frontend](#frontend)
* [API](#api)
* [Status Page](#status)
* [Governance & Support](#support)

<a name="about"></a>
# Carbon Registry
The National Carbon Registry enables carbon credit trading in order to reduce greenhouse gas emissions.

Expand All @@ -11,14 +24,94 @@ The system has 3 key features:
* **Carbon Credit Calculator:** Standardized system According to the UNFCCC - CDM (Clean Development Mechanism) methodologies, across defined sectors.
* **Serial Number Generator:** Standardizing the technical format to allow for easy cross-border collaboration between carbon trading systems.

## Standard
<a name="standards"></a>
## Standards
This codebase aims to fullfill the digital public goods standard:
https://digitalpublicgoods.net/standard/
It is built according to the Principles for Digital Development:
https://digitalprinciples.org/

<a name="architecture"></a>
## System Architecture
UNDP Carbon Registry based on Serverless Architecture.
UNDP Carbon Registry based on Serverless Architecture. It can be ported and hosted on any Function As A Service (FaaS) stack.
![alt text](./documention/imgs/System%20Architecture.png)

Carbon Registry backend system has a service oriented architecture (SOA) and contains 4 main services.

<a name="services"></a>
### **Services**
#### *National Service*

Authenticate, Validate and Accept user (Government, Programme Developer/Certifier) API request related to following functionalities,
- User and company CRUD operations.
- User authentication.
- Programme life cycle management.
- Credit life cycle management.

Service is horizontally scalable and state maintained in the following locations,
- File storage.
- Operational Database.
- Ledger Database.

Uses the Carbon Credit Calculator and Serial Number Generator node modules to estimate the programme carbon credit amount and issue a serial number.
Uses Ledger interface to persist programme and credit life cycles.

#### *Analytics Service*
Serve all the system analytics. Generate all the statistic using the operational database.
Horizontally scalable.

#### *Replicator Service*
Replicating ledger database new items to a operational database asynchronously. During the replication process it is injecting additional query information to the data.
In the current setup using AWS QLDB for the ledger database. When it creates or updates data, add the change to a AWS Kinesis Data Stream. Replicator service is consuming the stream.

#### *Operational Service*
Service that use to do system operations,
1. Database migrations.
2. User data creation and update.
3. Resource creation.

Can trigger internally. Cannot invoke by external sources.

### **Database Architecture**
primary/secondary database architecture using for carbon programme and account balances.
Ledger database - Primary database. Add/update programmes and update account balances in single transaction. Currently implemented only for AWS QLDB

Operational Database - Secondary database. Eventually add data for query purposes though replicator and data stream. Implemented based on PostgresSQL

**Why Two Database Approach?**
1. Cost and Query capabilities - Ledger database (blockchain) read capabilities can be limited and costly. To support rich statistics, replicated data in to a cheap query database.
2. Disaster recovery
3. Scalability - Primary/secondary database architecture is scalable since additional secondary databases can be added as needed to handle more read operations.

**Why Ledger Database?**
1. Immutable and Transparent - Track and maintain a sequenced history of every carbon programme and credit change.
2. Data Integrity (Cryptographic verification by third party).
3. Reconcile carbon credit and company account balance.

**Ledger Database Interface**

This enables the capability to add any blockchain or ledger database support to the carbon registry without application changes. Currently for the production system interface implemented for AWS QLDB. For testing purposes interface implemented for PostgresSQL as well.



Single database approach use for user and company management.


### **Ledger Layout**
Carbon Registry contains 3 ledger tables.
1. Programme ledger - Contains all the programme and credit transactions.
2. Company Account Ledger (Credit) - Contains company accounts credit transactions.
3. Country Account Ledger (Credit) - Contains country credit transactions.

Below diagram demonstrate the the ledger behavior on programme create, authorise, issue and transfer processes. Blue color document denotes a single data block in a ledger.

![alt text](./documention/imgs/Ledger.png)

### **Authentication**
- JWT Authentication - All endpoints based on role permissions.
- API Key Authentication - MRV System connectivity.

<a name="structure"></a>
## Project Structure

.
Expand All @@ -41,6 +134,7 @@ UNDP Carbon Registry based on Serverless Architecture.
├── .gitignore
└── README.md

<a name="local"></a>
## Run Services Locally
- Setup postgreSQL locally and create a new database.
- Update following DB configurations in the .env.local file (If file does not exist please create a new .env.local)
Expand All @@ -55,6 +149,7 @@ UNDP Carbon Registry based on Serverless Architecture.
- Start all the services by executing `sls offline --stage=local`
- Now all the system services are up and running. Swagger documentation will be available on `http://localhost:3000/local/national`

<a name="cloud"></a>
## Deploy System on the AWS Cloud
- Execute to create all the required resources on the AWS.
```
Expand Down Expand Up @@ -83,7 +178,7 @@ Carbon credit calculation implemented in a separate node module. [Please refer t
### Serial Number Generation
Serial Number generation implemented in a separate node module. [Please refer this](./libs/serial-number-gen/README.md) for more information.


<a name="user"></a>
## User Onboarding and Permissions Model

### User Roles
Expand Down Expand Up @@ -115,14 +210,23 @@ All the CRUD operations can perform as per the following table,
- All users can edit own user account except Role and Email.
- Users are not allowed to delete the own account from the system.


<a name="frontend"></a>
### Web Frontend
Web frontend implemented using ReactJS framework. Please refer [getting started with react app](./web/README.md) for more information.


<a name="api"></a>
### Application Programming Interface (API)
For integration, reference RESTful Web API Documentation documentation via Swagger. To access
- National API: api.APP_URL/national
- Status API: api.APP_URL/stats

<a name="status"></a>
### Status Page
https://github.com/undp/carbon-registry-status
For transparent uptime monitoring go to status.APP_URL
Open source code available at https://github.com/undp/carbon-registry-status

<a name="support"></a>
### Governance and Support
![undp-logo-blue](https://user-images.githubusercontent.com/109564/160651473-6d8daf4d-77fa-41ff-855c-43a0512353b6.svg) With funding, coordination and support from [United Nations Development Programme](https://www.undp.org)

Expand Down
42 changes: 42 additions & 0 deletions TOR National Implementation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
The following work steps are required for the national implementation of the DPG carbon registry in any country.

- Installation of a Carbon Registry from https://github.com/undp/carbon-registry

- Initial Setup of the Carbon Registry, including localization to national requirements:
- translation into relevant national languages *(Link to the .json/yaml files that need translation HERE)*
- adjust sectors to match the sectors specified in the nationally determined contribution *(link to file that specifies sectors HERE)*
- integration with existing NDC management tools (if applicable)
- adjustment of user types to national requirements
- creation of government accounts
*(Deliverable: Fully localized Carbon Registry running on test environment)*

- Successful end-to-end test of the registry. This test needs to cover the full lifecycle of one dummy project including at least project creation, authorization, implementation, MRV, issuance and transfer.
*(Deliverable: Test Report)*
- Creation of a nationally appropriate signup proceedure for non-government accounts
- Hand over to official government use
*(Deliverable: Government Acceptance)*

- Long term hosting and DevOps of the registry

Sample Terms of Reference
The TOR can be further specified if national details are known, e.g. about the NDC management tool.
These worksteps can also be intergrated with larger TORs, especially TORs covering wider NDC management / transparency. Below are sample phrases that may be used. Generally a vendor (firm) or a group of individual consultant are encouraged, as the required skills vary.

1. Scope of Work

3. Deliverables
- Deliverable 1:
- Deliverable 2:
- Deliverable 3:
- Deliverable 4: Maintenance of the registry (This is optional, however highly recommended to ensure upgrade and security checks)

Other items to consider:
- Hosting / clound server:
- The ToR is based on the assumption that he government entity has or will prepare a hosting environment in a cloud server. If the government does not have a server space, consider if the vendor will need to host the registry. If so, consider if the vendor can be contracted for a long term.
- Server specs-

4. Required persons / skills
- Developer 1:
- Developer 2:
- Project manager:
- Carbon or stakeholder engagement expert (optional)
2 changes: 1 addition & 1 deletion documention/Carbon Registry Architecture.drawio

Large diffs are not rendered by default.

Binary file added documention/imgs/Ledger.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 0 additions & 3 deletions documention/imgs/Ledger.svg

This file was deleted.

Binary file modified documention/imgs/System Architecture.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 0 additions & 4 deletions documention/imgs/System Architecture.svg

This file was deleted.

6 changes: 3 additions & 3 deletions lambda/services/src/shared/company/company.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export class CompanyService {
true
);
await this.companyTransferCancel(companyId, `${remarks}#${user.companyId}#${user.id}#${SystemActionType.SUSPEND_AUTO_CANCEL}#${company.name}`);
this.emailHelperService.sendEmail(company.email,EmailTemplates.PROGRAMME_DEVELOPER_ORG_DEACTIVATION,{},user.companyId)
await this.emailHelperService.sendEmail(company.email,EmailTemplates.PROGRAMME_DEVELOPER_ORG_DEACTIVATION,{},user.companyId)
} else if (company.companyRole === CompanyRole.CERTIFIER) {
await this.programmeLedgerService.revokeCompanyCertifications(
companyId,
Expand All @@ -102,7 +102,7 @@ export class CompanyService {
}
);

this.emailHelperService.sendEmail(company.email,EmailTemplates.CERTIFIER_ORG_DEACTIVATION,{},user.companyId)
await this.emailHelperService.sendEmail(company.email,EmailTemplates.CERTIFIER_ORG_DEACTIVATION,{},user.companyId)
}
return new BasicResponseDto(
HttpStatus.OK,
Expand Down Expand Up @@ -154,7 +154,7 @@ export class CompanyService {
this.getUserRefWithRemarks(user, `${remarks}#${company.name}`),
false
);
this.emailHelperService.sendEmail(company.email,EmailTemplates.ORG_REACTIVATION,{},user.companyId);
await this.emailHelperService.sendEmail(company.email,EmailTemplates.ORG_REACTIVATION,{},user.companyId);
return new BasicResponseDto(
HttpStatus.OK,
"Successfully activated company"
Expand Down
52 changes: 29 additions & 23 deletions lambda/services/src/shared/email-helper/email-helper.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ export class EmailHelperService {
programmeId: string,
template: any,
templateData: {},
companyId ?: number,
companyId?: number,
governmentId?: number
) {
const programme = await this.programmeLedger.getProgrammeById(programmeId);
const hostAddress = this.configService.get("host");
let companyDetails:Company;
let companyDetails: Company;

switch (template.id) {
case "PROGRAMME_REJECTION":
Expand All @@ -40,10 +40,8 @@ export class EmailHelperService {
};
break;

case 'PROGRAMME_CERTIFICATION':
companyDetails = await this.companyService.findByCompanyId(
companyId
);
case "PROGRAMME_CERTIFICATION":
companyDetails = await this.companyService.findByCompanyId(companyId);
templateData = {
...templateData,
programmeName: programme.title,
Expand All @@ -54,10 +52,8 @@ export class EmailHelperService {
};
break;

case 'PROGRAMME_CERTIFICATION_REVOKE_BY_CERT':
companyDetails = await this.companyService.findByCompanyId(
companyId
);
case "PROGRAMME_CERTIFICATION_REVOKE_BY_CERT":
companyDetails = await this.companyService.findByCompanyId(companyId);
templateData = {
...templateData,
programmeName: programme.title,
Expand All @@ -68,10 +64,8 @@ export class EmailHelperService {
};
break;

case 'PROGRAMME_CERTIFICATION_REVOKE_BY_GOVT_TO_PROGRAMME':
companyDetails = await this.companyService.findByCompanyId(
companyId
);
case "PROGRAMME_CERTIFICATION_REVOKE_BY_GOVT_TO_PROGRAMME":
companyDetails = await this.companyService.findByCompanyId(companyId);
const government = await this.companyService.findByCompanyId(
governmentId
);
Expand Down Expand Up @@ -225,18 +219,22 @@ export class EmailHelperService {
pageLink: hostAddress + "/creditTransfers/viewAll",
};
break;

default:
break;
}

users.forEach((user: any) => {
users.forEach(async (user: any) => {
templateData = {
...templateData,
name: user.user_name,
countryName: systemCountryName,
};
this.emailService.sendEmail(user.user_email, template, templateData);
await this.emailService.sendEmail(
user.user_email,
template,
templateData
);
});
}

Expand Down Expand Up @@ -291,25 +289,33 @@ export class EmailHelperService {
break;
}

users.forEach((user: any) => {
users.forEach(async (user: any) => {
templateData = {
...templateData,
name: user.user_name,
countryName: systemCountryName,
};
this.emailService.sendEmail(user.user_email, template, templateData);
await this.emailService.sendEmail(
user.user_email,
template,
templateData
);
});
}

public async sendEmail(sender: string, template, templateData: any, companyId: number){
public async sendEmail(
sender: string,
template,
templateData: any,
companyId: number
) {
const companyDetails = await this.companyService.findByCompanyId(companyId);
const systemCountryName = this.configService.get("systemCountryName");
templateData = {
...templateData,
countryName: systemCountryName,
government: companyDetails.name
government: companyDetails.name,
};
this.emailService.sendEmail(sender, template, templateData);
await this.emailService.sendEmail(sender, template, templateData);
}

}
7 changes: 3 additions & 4 deletions lambda/services/src/shared/email/email.template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ export const EmailTemplates = {
Password (temporary): {{tempPassword}} <br><br>

If you have any questions, feel free to email our customer success
team <a href="mailto:mailto: help@carbreg.org?subject=I Need Help With The
{{countryName}} Carbon Credit Registry">customer success team</a>
team <a href="mailto:help@carbreg.org?subject=I Need Help With The {{countryName}} Carbon Credit Registry">customer success team</a>
(We’re lightning quick at replying.) We also offer live chat {{liveChat}}.
<br><br>

Expand Down Expand Up @@ -86,7 +85,7 @@ export const EmailTemplates = {
},
CHANGE_PASSOWRD: {
id: 'CHANGE_PASSOWRD',
subject: 'Carbon Registry: Your password was changed',
subject: 'Your password was changed',
html: `
Hi {{name}},<br><br>
The password of your Carbon Registry account was changed successfully. <br><br>
Expand All @@ -108,7 +107,7 @@ export const EmailTemplates = {

A new programme owned by {{organisationName}} is awaiting authorisation. <br><br>

<a href="{{programmePageLink}}">Click here</a> to access all the programmes that require authorisation.
Click <a href="{{programmePageLink}}">here</a> to access all the programmes that require authorisation.
<br><br>

Sincerely, <br>
Expand Down
Loading