carboncreditsbacklog/interfaz.js

591 lines
25 KiB
JavaScript

//Required inquier, ipfsclient, moment, OrbitDB, fs
const IpfsClient = require('ipfs-http-client');
const OrbitDB = require('orbit-db');
let inquirer = require('inquirer');
let moment = require('moment');
let hasher = require('node-object-hash')
const fs = require('fs');
const addressDB = 'decaCCDB';
//A instance of ipfs locally in ipfs daemon
const ipfs = IpfsClient('http://localhost:5001');
//Required module divisaTraceback to get all the prices
var divisaTraceback = require('./divisaTraceback');
const hashSortCoerce = hasher({ sort: true, coerce: true });
//Function to start application
const main = async () => {
const orbitdb = await OrbitDB.createInstance(ipfs)
const db = await orbitdb.docs(addressDB, { indexBy: 'CCID' });
await db.load();
while (true) {
await init();
let { mainMenu } = await inquirer.prompt([{
type: 'list',
name: 'mainMenu',
message: 'Select an action',
choices: [
'Show carbon credit records',
'Insert carbon credit',
'Search carbon credits',
'Delete carbon credit',
'Exit'
]
}]);
if (mainMenu == 'Show carbon credit records') {
let data = db.get('');
while (true) {
let { showMenu } = await inquirer.prompt([{
type: 'list',
name: 'showMenu',
message: 'Select an option',
choices: [
'Show in terminal',
'Save as JSON',
'Save as CSV',
'Back to main menu'
]
}]);
if (showMenu == 'Show in terminal') {
for (element in data) {
showData(data[element], 0);
console.log('-------------------------------------\n');
}
} else if (showMenu == 'Save as JSON') {
fs.writeFileSync(`/tmp/${moment().format()}.json`, JSON.stringify(data));
console.log(`File saved in /tmp/${moment().format()}.json`);
} else if (showMenu == 'Save as CSV') {
let csv = '';
for (element in data) csv += await JSONToCSV(data[element]);
fs.writeFileSync(`/tmp/${moment().format()}.csv`, csv);
console.log(`File saved in /tmp/${moment().format()}.csv`);
}
else if (showMenu == 'Back to main menu') {
break;
}
}
console.clear();
}
else if (mainMenu == 'Insert carbon credit') {
let carbonCredit = {
cancelPrice: undefined,
SerialNo: undefined,
issueDate: undefined,
cancelDate: undefined,
ccVintageStart: undefined,
ccVintageEnd: undefined,
ccCategory: undefined,
ccMeasurement: undefined,
ccStandard: undefined,
countryCode: undefined,
ccProjectID: undefined,
ccAddress: undefined,
CCAdquisitionRecipt: undefined,
cancelRemaks: undefined,
cancelPrice: {
qty: undefined,
divisa: undefined
}
}
while (true) {
await init();
console.clear();
console.log('Select one to modify the field.\n');
let carbonCreditMenu = await generateData(carbonCredit, 0);
let { insertMenu } = await inquirer.prompt([{
type: 'list',
pageSize: 24,
name: 'insertMenu',
message: 'Select a field/action',
choices: carbonCreditMenu.concat([
new inquirer.Separator(),
{
name: 'Actions',
disabled: ' '
},
'Insert current register',
'Back to main menu'
])
}]);
if (insertMenu == 'Insert current register') {
if (await validateInsertion(carbonCredit)) {
carbonCredit.conversionPrice = await divisaTraceback(
moment.utc(carbonCredit.cancelDate + ' +0000', 'DD-MM-YYYY HH:mm Z').unix(),
carbonCredit.cancelPrice.divisa,
carbonCredit.cancelPrice.qty
);
showData(carbonCredit, 0);
serialNoPart=carbonCredit.SerialNo.split('-');
serialFloor=serialNoPart[7];
serialTop=serialNoPart[8];
var totalCC = 1+parseInt(serialTop)-parseInt(serialFloor);
let { input } = await inquirer.prompt([{
type: 'input',
name: 'input',
message: 'Data is correct, you will insert '+ String(totalCC) +" carbon credits y | n:",
}]);
if (input == 'y') {
carbonCredit.issueDate = moment(carbonCredit.issueDate + ' +0000', 'DD-MM-YYYY HH:mm Z').unix();
carbonCredit.cancelDate = moment(carbonCredit.cancelDate + ' +0000', 'DD-MM-YYYY HH:mm Z').unix();
carbonCredit.ccVintageStart = moment(carbonCredit.ccVintageStart + ' +0000', 'DD-MM-YYYY HH:mm Z').unix();
carbonCredit.ccVintageEnd = moment(carbonCredit.ccVintageEnd + ' +0000', 'DD-MM-YYYY HH:mm Z').unix();
carbonCredit.CCID = await hashSortCoerce.hash(carbonCredit);
const hash = await db.put(carbonCredit);
console.log(`Successful insertion, CCID: ${carbonCredit.CCID}, hash: ${hash}.`);
for(var i=parseInt(serialFloor)+1; i<=serialTop; i++){
var tempCarbonCredit = {...carbonCredit};
tempCarbonCredit.SerialNo= await asyncCCSerialNo(serialNoPart,i)
tempCarbonCredit.CCID = await hashSortCoerce.hash(tempCarbonCredit);
const hash = await db.put(tempCarbonCredit);
console.log(`Successful insertion, CCID: ${tempCarbonCredit.CCID}, hash: ${hash}.`);
}
console.log(`Inserted ${totalCC} carbon credits.`);
break;
} else {
console.clear();
console.log('Insertion aborted');
break;
}
}
else {
await showErrorData(carbonCredit);
}
}
else if (insertMenu == 'Back to main menu') {
console.clear();
break;
}
else {
let subValue = false;
if (insertMenu[0] == ' ') {
insertMenu = insertMenu.trimStart().split(" ")[0];
subValue = true;
} else insertMenu = insertMenu.split(" ")[0];
if (insertMenu == 'divisa') {
let { currency } = await inquirer.prompt([{
type: 'list',
name: 'currency',
message: 'Choose a currency',
choices: ['BTC', 'ETH', 'LTC', 'USD', 'GBP', 'CNY', 'EUR']
}]);
carbonCredit.cancelPrice[insertMenu] = currency;
}
else {
let { input } = await inquirer.prompt([{
type: 'input',
name: 'input',
message: insertMenu + ': ',
}]);
if (input == '') console.log('Input mustn\'t be empty');
else if (insertMenu == 'issueDate' || insertMenu == 'cancelDate' || insertMenu == 'ccVintageStart' || insertMenu == 'ccVintageEnd') {
const date = moment.utc(input + ' +0000', 'DD-MM-YYYY HH:mm');
if (date.isValid() && insertMenu == 'cancelDate' && moment() >= date && date >= moment().subtract(10, 'days')) {
carbonCredit[insertMenu] = date.format('DD-MM-YYYY HH:mm Z');
}
else if (date.isValid() && insertMenu != 'cancelDate' && moment() >= date) {
carbonCredit[insertMenu] = date.format('DD-MM-YYYY HH:mm Z');
} else console.log(' Date must follow next syntax: dd-mm-yyyy hh-mm and cancel date must be 10 days old at most');
}
else if (insertMenu == 'qty') {
if (parseFloat(input)) carbonCredit.cancelPrice[insertMenu] = input;
else console.log('This must be a number');
}
else {
if (subValue) carbonCredit.cancelPrice[insertMenu] = input;
else carbonCredit[insertMenu] = input;
}
}
}
}
}
else if (mainMenu == 'Search carbon credits') {
let { searchMenu } = await inquirer.prompt([{
type: 'list',
name: 'searchMenu',
message: 'Search carbon credit by:',
choices: [
'Category',
'CCID',
'Standard',
'Project Id',
'Vintage Date',
'Adquisition Recipt',
'Back to main menu'
]
}]);
if (searchMenu == 'Category') {
let { input } = await inquirer.prompt([{
type: 'input',
name: 'input',
message: 'Category: ',
}]);
let { confirm } = await inquirer.prompt([{
type: 'input',
name: 'confirm',
message: 'Confirm y | n: ',
}]);
if (confirm == 'y') {
const all = db.query((doc) => doc.ccCategory == input);
if (all.length > 0) {
let choicesSearch = await elemSearch(all);
await inquirer.prompt([{
type: 'list',
name: 'CCID',
message: 'Select CCID',
choices: choicesSearch
}]).then(answer => {
console.log(db.get(answer.CCID))
})
} else {
console.clear();
console.log("No registries found")
}
} else {
console.clear();
console.log('Search canceled');
}
}
else if (searchMenu == 'CCID') {
let { input } = await inquirer.prompt([{
type: 'input',
name: 'input',
message: 'CCID: ',
}]);
let { confirm } = await inquirer.prompt([{
type: 'input',
name: 'confirm',
message: 'Confirm y | n: ',
}]);
if (confirm == 'y') {
console.log(db.get(input))
} else {
console.clear();
console.log('Search canceled');
}
}
else if (searchMenu == 'Standard') {
let { input } = await inquirer.prompt([{
type: 'input',
name: 'input',
message: 'Standard: ',
}]);
let { confirm } = await inquirer.prompt([{
type: 'input',
name: 'confirm',
message: 'Confirm y | n: ',
}]);
if (confirm == 'y') {
const all = db.query((doc) => doc.ccStandard == input);
if (all.length > 0) {
let choicesSearch = await elemSearch(all);
await inquirer.prompt([{
type: 'list',
name: 'CCID',
message: 'Select CCID',
choices: choicesSearch
}]).then(answer => {
console.log(db.get(answer.CCID))
})
} else {
console.clear();
console.log("No registries found")
}
} else {
console.clear();
console.log('Search canceled');
}
}
else if (searchMenu == 'Project Id') {
let { input } = await inquirer.prompt([{
type: 'input',
name: 'input',
message: 'ProjectID: ',
}]);
let { confirm } = await inquirer.prompt([{
type: 'input',
name: 'confirm',
message: 'Confirm y | n: ',
}]);
if (confirm == 'y') {
const all = db.query((doc) => doc.ccProjectID == input);
if (all.length > 0) {
let choicesSearch = await elemSearch(all);
await inquirer.prompt([{
type: 'list',
name: 'CCID',
message: 'Select CCID',
choices: choicesSearch
}]).then(answer => {
console.log(db.get(answer.CCID))
})
} else {
console.clear();
console.log("No registries found")
}
} else {
console.clear();
console.log('Search canceled');
}
}
else if (searchMenu == 'Vintage Date') {
let { vintageMenu } = await inquirer.prompt([{
type: 'list',
name: 'vintageMenu',
message: 'Search carbon credit by:',
choices: [
'Vintage Start',
'Vintage End',
'Back to main menu'
]
}]);
if (vintageMenu == 'Vintage Start') {
let { input } = await inquirer.prompt([{
type: 'input',
name: 'input',
message: 'Vintage Start: ',
}]);
let { confirm } = await inquirer.prompt([{
type: 'input',
name: 'confirm',
message: 'Confirm y | n: ',
}]);
if (confirm == 'y') {
let date = moment.utc(input + ' +0000', 'DD-MM-YYYY HH:mm');
date = date.format('DD-MM-YYYY HH:mm Z')
const all = db.query((doc) => doc.ccVintageStart == moment(date + ' +0000', 'DD-MM-YYYY HH:mm Z').unix());
if (all.length > 0) {
let choicesSearch = await elemSearch(all);
await inquirer.prompt([{
type: 'list',
name: 'CCID',
message: 'Select CCID',
choices: choicesSearch
}]).then(answer => {
console.log(db.get(answer.CCID))
})
} else {
console.clear();
console.log("No registries found")
}
} else {
console.clear();
console.log('Search canceled');
}
} else if (vintageMenu == 'Vintage End') {
let { input } = await inquirer.prompt([{
type: 'input',
name: 'input',
message: 'Vintage End: ',
}]);
let { confirm } = await inquirer.prompt([{
type: 'input',
name: 'confirm',
message: 'Confirm y | n: ',
}]);
if (confirm == 'y') {
let date = moment.utc(input + ' +0000', 'DD-MM-YYYY HH:mm');
date = date.format('DD-MM-YYYY HH:mm Z')
const all = db.query((doc) => doc.ccVintageEnd == moment(date + ' +0000', 'DD-MM-YYYY HH:mm Z').unix());
if (all.length > 0) {
let choicesSearch = await elemSearch(all);
await inquirer.prompt([{
type: 'list',
name: 'CCID',
message: 'Select CCID',
choices: choicesSearch
}]).then(answer => {
console.log(db.get(answer.CCID))
})
} else {
console.clear();
console.log("No registries found")
}
} else {
console.clear();
console.log('Search canceled');
}
} else if (vintageMenu == 'Back to main menu') {
console.clear();
console.log('Search canceled');
}
}
else if (searchMenu == 'Adquisition Recipt') {
let { input } = await inquirer.prompt([{
type: 'input',
name: 'input',
message: 'Adquisition Recipt: ',
}]);
let { confirm } = await inquirer.prompt([{
type: 'input',
name: 'confirm',
message: 'Confirm y | n: ',
}]);
if (confirm == 'y') {
const all = db.query((doc) => doc.CCAdquisitionRecipt == input);
if (all.length > 0) {
let choicesSearch = await elemSearch(all);
await inquirer.prompt([{
type: 'list',
name: 'CCID',
message: 'Select CCID',
choices: choicesSearch
}]).then(answer => {
console.log(db.get(answer.CCID))
})
} else {
console.clear();
console.log("No registries found")
}
} else {
console.clear();
console.log('Search canceled');
}
}
else if (searchMenu == 'Back to main menu') {
console.clear();
console.log("Search Canceled");
}
}
else if (mainMenu == 'Delete carbon credit') {
let { input } = await inquirer.prompt([{
type: 'input',
name: 'input',
message: 'CCID: ',
}]);
if (input.length > 0) {
const all = db.query((doc) => doc.CCID == input)
if (all.length > 0) {
console.log(all);
let { confirm } = await inquirer.prompt([{
type: 'input',
name: 'confirm',
message: 'Confirm y | n: ',
}]);
if (confirm == 'y') {
console.clear();
const hash = await db.del(input);
console.log(`${input} deleted succesfully`);
} else {
console.clear();
console.log('Delete aborted');
}
} else {
console.clear();
console.log("Error not found registry")
}
} else {
console.clear();
console.log("Error")
}
}
else if (mainMenu == 'Exit') {
await orbitdb.disconnect();
process.exit();
}
else {
console.log(`Error. The option is invalid.`);
process.exit();
}
}
};
const init = async () => {
let output = ' ____ _ _ _ _____ ______ _____ _ _____ _____ \n';
output += ' / __ \\ | | (_) | | | __ \\ | ____| / ____| / \\ / ____| / ____|\n';
output += ' | | | | _ __ | |__ _ | |_ | | | | | |__ | | / \\ | | | | \n';
output += ' | | | | | \'__| | \'_ \\ | | | __| | | | | | __| | | / /_\\ \\ | | | | \n';
output += ' | |__| | | | | |_) | | | | |_ | |__| | | |____ | |____ / _____ \\ | |____ | |____ \n';
output += ' \\____/ |_| |_.__/ |_| \\__| |_____/ |______| \\_____| /_/ \\_\\ \\_____| \\_____|\n';
output += ' Interfaz\n';
console.log(output);
}
const elemSearch = async (objectSearch) => {
let elems = [];
for (let key in objectSearch) {
elems.push(objectSearch[key]['CCID']);
}
return elems;
}
const generateData = async (data, n) => {
let menu = [];
let tab = ' '.repeat(n);
for (element in data) {
if (typeof (data[element]) == 'object') {
menu.push({ name: element, disabled: ' ' });
menu = menu.concat(await generateData(data[element], n + 1));
} else {
let space = ' '.repeat(20 - element.length);
space = space.substring(0, space.length - tab.length);
menu.push(`${tab}${element}${space}${data[element]}`);
}
}
return menu;
}
const asyncCCSerialNo = async (serialNoPart, index) => {
serialNoPart[7] = String(index);
return serialNoPart.join('-');
}
//Show carbon credit data
const showData = async (data, n) => {
for (element in data) {
for (let i = 0; i < n; i++) process.stdout.write('\t');
if (typeof (data[element]) == 'object') {
console.log(` ${element}:`);
showData(data[element], n + 1);
}
if (data[element] != undefined) console.log(` ${element}: ${data[element]}`);
}
}
//Validate data received
const validateInsertion = async (data) => {
for (element in data) {
if (typeof (data[element]) == 'object') {
validateInsertion(data[element]);
}
else if (data[element] == undefined) {
return false;
}
}
return true;
}
//Show error in field
const showErrorData = async (data) => {
let errorfields = '';
for (element in data) {
if (typeof (data[element]) == 'object') {
validateInsertion(data[element]);
}
else if (data[element] == undefined) errorfields += element + '\n';
}
console.log('The following fields have not been filled correctly:');
console.log(errorfields);
}
//Parse json to csv
const JSONToCSV = async (data, n) => {
let csv = '';
for (element in data) {
if (typeof (data[element]) == 'object') {
validateInsertion(data[element]);
}
else csv += `${data[element]}, `
}
if (n == 0) csv += '\n';
return csv;
}
//Call index function
main();