Newer
Older
const soapRequest = require('easy-soap-request')
const moment = require('moment')
require('moment-timezone')
const xml2js = require('xml2js')
const { buildAgregatedData } = require('./helpers/aggregate')
const {
parseSgeXmlData,
formateDataForDoctype,
parseTags,
parseValue,
consulterDonneesTechniquesContractuelles,
consultationMesuresDetailleesMaxPower,
consultationMesuresDetaillees,
} = require('./requests/sge')
const {
const { verifyUserIdentity } = require('./core/verifyUserIdentity')
const { activateContract } = require('./core/contractActivation')
const { verifyContract } = require('./core/contractVerification')
const { terminateContract } = require('./core/contractTermination')
const { getAccount, saveAccountData } = require('./requests/cozy')
moment.locale('fr') // set the language
moment.tz.setDefault('Europe/Paris') // set the timezone
/*** Connector Constants ***/
const manualExecution =
process.env.COZY_JOB_MANUAL_EXECUTION === 'true' ? true : false
? moment().subtract(12, 'month')
: moment().subtract(6, 'month')
let startDailyDateString = startDailyDate.format('YYYY-MM-DD')
const startLoadDate = moment().subtract(7, 'day')
const endDate = moment()
const endDateString = endDate.format('YYYY-MM-DD')
const ACCOUNT_ID = iSLocal() ? 'default_account_id' : 'enedis-sge-grandlyon'
/**
* The start function is run by the BaseKonnector instance only when it got all the account
* information (fields). When you run this connector yourself in "standalone" mode or "dev" mode,
* the account information come from ./konnector-dev-config.json file
* cozyParameters are static parameters, independents from the account. Most often, it can be a
* secret api key.
* @param {fields} fields
* @param {{secret: fields}} cozyParameters
*/
let baseUrl = fields.wso2BaseUrl
let apiAuthKey = fields.apiToken
//TODO: Verify if condition is working in local and on build version
if (cozyParameters && Object.keys(cozyParameters).length !== 0) {
log('debug', 'Found COZY_PARAMETERS')
baseUrl = cozyParameters.secret.wso2BaseUrl
apiAuthKey = cozyParameters.secret.apiToken
sgeLogin = cozyParameters.secret.sgeLogin
/**
* If it's first start we have to do the following operations:
* - verify pdl are matching
* - BO: create backoffice consent
* - get contract start date and store it
* - activate half-hour
* - BO: update consent with service ID
*/
log('info', 'User Logging...')
if (await isFirstStart(await getAccount('default_account_id'))) {
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
const user = await verifyUserIdentity(fields, baseUrl, apiAuthKey, sgeLogin)
let consent = await createBoConsent(
pointId,
user.name,
user.address,
user.postalCode,
user.inseeCode
)
await getContractStartDate(baseUrl, apiAuthKey, sgeLogin, pointId)
const contractStartDate = moment().format('YYYY-MM-DD')
//TODO: consent time ? 5 years?
const contractEndDate = moment()
.add(1, 'year')
.format('YYYY-MM-DD')
let serviceId = await verifyContract(
baseUrl,
apiAuthKey,
sgeLogin,
fields.contractId,
user.pointId
)
if (!serviceId) {
serviceId = await activateContract(
baseUrl,
apiAuthKey,
sgeLogin,
fields.contractId,
user.name,
user.pointId,
contractStartDate,
contractEndDate
)
}
consent = await updateBoConsent(consent, serviceId)
// Save bo id into account
const accountData = await getAccount(ACCOUNT_ID)
console.log(
'🚀 ~ file: index.js ~ line 132 ~ start ~ accountData',
accountData
)
await saveAccountData(this.accountId, {
...accountData.data,
consentId: consent.id,
})
const accountData = await getAccount(ACCOUNT_ID)
const userConsent = await getBoConsent(accountData.data.consentId)
const user = await verifyUserIdentity(fields, baseUrl, apiAuthKey, sgeLogin)
if (user.name !== userConsent.name || !user) {
log('error', `Invalid or not found consent for user`)
if (userConsent.serviceId) {
await terminateContract(
baseUrl,
apiAuthKey,
sgeLogin,
fields.contractId,
fields.pointId,
userConsent.serviceId
)
} else {
log('error', `No service id retrieved from BO`)
throw errors.VENDOR_DOWN
}
throw errors.TERMS_VERSION_MISMATCH
}
}
await gatherData(baseUrl, apiAuthKey, sgeLogin, fields.pointId)
}
/**
* Main method for gathering data
* @param {string} baseUrl
* @param {string} apiAuthKey
async function gatherData(baseUrl, apiAuthKey, sgeLogin, pointId) {
await getContractStartDate(baseUrl, apiAuthKey, sgeLogin, pointId)
await getData(
`${baseUrl}/enedis_SGE_ConsultationMesuresDetaillees/1.0`,
apiAuthKey,
await getMaxPowerData(
`${baseUrl}/enedis_SGE_ConsultationMesuresDetaillees/1.0`,
apiAuthKey,
await getDataHalfHour(
`${baseUrl}/enedis_SGE_ConsultationMesuresDetaillees/1.0`,
apiAuthKey,
* @param {string} url
* @param {string} apiAuthKey
* @param {string} userLogin
* @param {number} pointId
async function getContractStartDate(url, apiAuthKey, userLogin, pointId) {
'Content-Type': 'text/xml;charset=UTF-8',
apikey: apiAuthKey,
}
const { response } = await soapRequest({
url: `${url}/enedis_SGE_ConsultationDonneesTechniquesContractuelles/1.0`,
xml: consulterDonneesTechniquesContractuelles(pointId, userLogin),
log('error', 'Error while fetching contract start date : ' + err)
throw errors.VENDOR_DOWN
})
xml2js.parseString(
response.body,
{
tagNameProcessors: [parseTags],
valueProcessors: [parseValue],
explicitArray: false,
},
processStartDate()
)
}
* @param {string} url
* @param {string} apiAuthKey
* @param {string} userLogin
* @param {number} pointId
*/
async function getData(url, apiAuthKey, userLogin, pointId) {
log('info', 'Fetching data')
'Content-Type': 'text/xml;charset=UTF-8',
apikey: apiAuthKey,
}
const { response } = await soapRequest({
url: url,
pointId,
userLogin,
startDailyDateString,
tagNameProcessors: [parseTags],
valueProcessors: [parseValue],
explicitArray: false,
/**
* Get Max power data
* @param {string} url
* @param {string} apiAuthKey
* @param {string} userLogin
* @param {number} pointId
*/
async function getMaxPowerData(url, apiAuthKey, userLogin, pointId) {
log('info', 'Fetching Max Power data')
'Content-Type': 'text/xml;charset=UTF-8',
apikey: apiAuthKey,
}
const { response } = await soapRequest({
url: url,
xml: consultationMesuresDetailleesMaxPower(
pointId,
userLogin,
startDailyDateString,
endDateString
),
}).catch(err => {
log('error', 'getMaxPowerData')
log('error', err)
return err
})
xml2js.parseString(
response.body,
{
tagNameProcessors: [parseTags],
valueProcessors: [parseValue],
explicitArray: false,
},
processData('com.grandlyon.enedis.maxpower')
)
}
/**
* If start date exceed the maximum amount of data we can get with one query
* get only 36 month
*/
function setStartDate() {
if (moment(endDate).diff(startDailyDate, 'months', true) > 36) {
log(
'info',
'Start date exceed 36 month, setting start date to current date minus 36 month'
)
startDailyDate = moment(endDate).subtract(36, 'month')
startDailyDateString = startDailyDate.format('YYYY-MM-DD')
}
}
/**
* Get half-hour data
* @param {string} url
* @param {string} apiAuthKey
* @param {string} userLogin
* @param {number} pointId
*/
async function getDataHalfHour(url, apiAuthKey, userLogin, pointId) {
log('info', 'Fetching data')
'Content-Type': 'text/xml;charset=UTF-8',
apikey: apiAuthKey,
}
let MAX_HISTO = 4
// If manual execution, retrieve only 1 week
if (manualExecution) {
MAX_HISTO = 1
}
for (var i = 0; i < MAX_HISTO; i++) {
log('info', 'launch process with history')
const increamentedStartDateString = moment(startLoadDate)
.subtract(7 * i, 'day')
.format('YYYY-MM-DD')
const incrementedEndDateString = moment(endDate)
.subtract(7 * i, 'day')
.format('YYYY-MM-DD')
const { response } = await soapRequest({
url: url,
pointId,
userLogin,
increamentedStartDateString,
incrementedEndDateString,
'COURBE',
'PA'
),
}).catch(err => {
log('error', 'consultationMesuresDetaillees half-hour')
log('error', err)
return err
})
xml2js.parseString(
response.body,
{
tagNameProcessors: [parseTags],
valueProcessors: [parseValue],
explicitArray: false,
},
processData('com.grandlyon.enedis.minute')
)
}
}
function processData(doctype = 'com.grandlyon.enedis.day') {
return async (err, result) => {
if (err) {
log('error', err)
throw err
}
// Return only needed part of info
const data = parseSgeXmlData(result)
doctype,
['year', 'month', 'day', 'hour', 'minute']
log('info', 'Agregate enedis daily data for month and year')
if (doctype === 'com.grandlyon.enedis.day') {
await agregateMonthAndYearData(processedDailyData)
}
*/
function processStartDate() {
return async (err, result) => {
if (err) {
log('error', err)
throw err
}
// update start Date with contract openning date
startDailyDate = moment(parseContractStartDate(result), 'YYYY-MM-DD')
startDailyDateString = startDailyDate.format('YYYY-MM-DD')
} catch (error) {
log('error', 'Error while processing contract start date: ' + error)
throw errors.NOT_EXISTING_DIRECTORY
/**
* Save data in the right doctype db and prevent duplicated keys
* @param {EnedisKonnectorData[]} data
* @param {string} doctype
* @param {string[]} filterKeys
*/
async function storeData(data, doctype, filterKeys) {
log('debug', doctype, 'Store into')
const filteredDocuments = await hydrateAndFilter(data, doctype, {
keys: filterKeys,
})
await addData(filteredDocuments, doctype)
return filteredDocuments
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
/**
* Agregate data from daily data to monthly and yearly data
*/
async function agregateMonthAndYearData(data) {
// Sum year and month values into object with year or year-month as keys
if (data && data.length > 0) {
let monthData = {}
let yearData = {}
data.forEach(element => {
element.year + '-' + element.month in monthData
? (monthData[element.year + '-' + element.month] += element.load)
: (monthData[element.year + '-' + element.month] = element.load)
element.year in yearData
? (yearData[element.year] += element.load)
: (yearData[element.year] = element.load)
})
// Agregation for Month data
const agregatedMonthData = await buildAgregatedData(
monthData,
'com.grandlyon.enedis.month'
)
await storeData(agregatedMonthData, 'com.grandlyon.enedis.month', [
'year',
'month',
])
// Agregation for Year data
const agregatedYearData = await buildAgregatedData(
yearData,
'com.grandlyon.enedis.year'
)
await storeData(agregatedYearData, 'com.grandlyon.enedis.year', ['year'])
}
}
console.log(account)
if (account && account.data && account.data.consentId) {
log('info', 'Konnector not first start')
return false
}
log('info', 'Konnector first start')