-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsend_to_mob_api.js
More file actions
186 lines (178 loc) · 7.7 KB
/
Copy pathsend_to_mob_api.js
File metadata and controls
186 lines (178 loc) · 7.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
const fs = require('fs');
const request = require('request');
// Token récupéré via l'authentification de l'utilisateur admin_fonctionnel
const API_TOKEN = "XX"
// Fichier csv source des aides, utilise le caractère "µ" comme séparateur.
// Chaque ligne d'aide doit se terminer par µµ (le plus simple est d'ajouter des colonnes avant l'export)
const CSV_FILENAME = "exemple.csv"
// URL de l'API moB
const API_URL = "http://.../v1/incentives"
// En cas d'invalidité du lien de souscription, un lien par défaut peut-être utilisé
const DEFAULT_SUBSCRIPTION_LINK = "http://..."
// Affiche les erreurs de formatage des aides
const STOP_ON_INVALID_INPUT = true
// Lance le script en mode test, les API ne seront pas appelées
const TEST_RUN_DO_NOT_SEND_TO_API = true
// Correspondance entre les colonnes de l'excel avec le nom des champs de l'API
const colMatch = {
'Cible': "",
"Nom de l'aide": "title",
"Proposition de valeur de l'aide": "description",
'Nom du territoire': "territoryName",
'Type de financeur': "incentiveType",
'Nom du financeur': "funderName",
"Conditions d'obtention (d'éligibilités)": "conditions",
"Conditions d'obtention": "conditions",
'Où et comment en bénéficier?': "",
'Modalités de versement': "paymentMethod",
'Montant': "allocatedAmount",
"Montant minimum de l'aide": "minAmount",
"Montant min / max de l'aide": "minAmount",
'Mode de transport': "transportList",
'Justificatifs': "",
'Bon à savoir ': "additionalInfos",
'Contact ': "contact",
'Durée de validité': "validityDuration",
// 'Date de fin de validité': "validityDate",
'Souscription via MCM ?': "isMCMStaff",
'Lien de souscription externe': "subscriptionLink",
"Source de l'information": "",
'Commentaires': ""
}
// Correspondance entre les types de transport de l'excel et les catégories acceptées par l'API
// l'API accepte les catégories suivantes: transportsCommun, velo, voiture, libreService, electrique, autopartage, covoiturage
const transportMatch = {
"Transports en commun": "transportsCommun",
"Transport en commun": "transportsCommun",
"Réseaux urbain et non urbain": "transportsCommun",
"Vélo": "velo",
"Vélo classique non électrique": "velo",
"Covoiturage": "covoiturage",
"VAE": "electrique",
"Vélo à assistance électrique": "electrique",
"Vélo à assistance électrique ou Vélo classique": "electrique",
"quadricycle électrique": "electrique",
"Vélo électrique": "electrique",
"Vél": "velo",
"Bus": "transportsCommun",
"bus": "transportsCommun",
"2, 3 roues ou quadricycle électrique": "electrique",
"2-roues electriques": "electrique",
"Voiture": "voiture",
"véhicules thermiques": "voiture",
"Camionnette": "voiture",
"2 ou 3 roues motorisé ou quadricycle électrique": "electrique",
// "Transport scolaire adapté": "",
// "Voiture adaptée": "",
// "Service de transport à la demande": "",
// "TAD": "",
}
// Correspondance sur le type d'aide
const incentiveMatch = {
"Aide nationale": "AideNationale",
"Aide de mon territoire": "AideTerritoire",
"Aide de mon employeur": "AideEmployeur"
}
// Fonctions de conversions entre cellules excel et format compatible avec l'API
// Par exemple, la liste des transports transforme "vélo ; Transports en commun" en ["velo", "transportsCommun"]
const convert = {
'incentiveType': (e => {
if (incentiveMatch[e]) return incentiveMatch[e]
if (STOP_ON_INVALID_INPUT) throw new Error("incentiveType invalide: " + e?.toString())
return ""
}),
'transportList': (e => {
const tlist = (e ? e.replace('"', '').split(/;|\n|,/).map(f => transportMatch[f.trim()] || (f.indexOf("liO") > -1 ? "transportsCommun" : "")).filter(f => f !== ""): [])
if (STOP_ON_INVALID_INPUT && tlist.length === 0 ) {
throw new Error("Aucune correspondance de transport trouvée ou champ vide: " + e?.toString())
}
return tlist
}),
'isMCMStaff': (e => e === "Oui"),
'subscriptionLink': (e => {
if (e && e.trim().match(/^(?:http(s)?:\/\/)[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)*\+,;=.]+$/)) return e
if (STOP_ON_INVALID_INPUT) throw new Error("subscriptionLink invalide (pas un lien) ou vide: " + e?.toString())
return DEFAULT_SUBSCRIPTION_LINK
}),
'minAmount': (e => {
if (e) return e
if (STOP_ON_INVALID_INPUT) throw new Error("minAmount invalide ou vide: " + e?.toString())
return "NA"
}),
'paymentMethod': (e => {
if (e) return e
if (STOP_ON_INVALID_INPUT) throw new Error("paymentMethod invalide ou vide: " + e?.toString())
return "NA"
}),
'title': (e => {
if (e) return e
if (STOP_ON_INVALID_INPUT) throw new Error("title invalide ou vide: " + e?.toString())
return ""
})
}
// Lecture du fichier csv
fs.readFile(CSV_FILENAME, 'utf8', (err, data) => {
if (err) {
console.error(err);
return;
}
// Le fichier initial contenant des retours à la ligne ('\n') dans les cellules,
// on utilise la répétition du délimiteur "µ" suivi du retour à la ligne pour séparer les aides
// On sépare ensuite les 21 premières colonnes
let parsed_data = data.split(/µµ\n/).map(e => e.split("µ").slice(0,21))
let incentives = []
// La première ligne de header est ignorée
for (var i = 1; i < parsed_data.length; i += 1) {
incentives.push({})
for (var j = 0; j < parsed_data[i].length; j += 1) {
// Pour chaque aide, on lit la ligne de header pour convertir le nom de colonne en champ API
let col = colMatch[parsed_data[0][j]]
// Si la correspondance existe, on ajoute le champ au dictionnaire
if (col)
incentives[incentives.length -1][col] = parsed_data[i][j].replace("-", "")
}
}
// Une fois toutes les aides ajoutées, on convertit les champs au bon format pour l'API via les fonctions de conversions
incentives = incentives.map(incentive => {
try {
incentive.incentiveType = convert.incentiveType(incentive.incentiveType)
incentive.transportList = convert.transportList(incentive.transportList)
incentive.isMCMStaff = convert.isMCMStaff(incentive.isMCMStaff)
incentive.minAmount = convert.minAmount(incentive.minAmount)
incentive.paymentMethod = convert.paymentMethod(incentive.paymentMethod)
incentive.title = convert.title(incentive.title)
incentive.subscriptionLink = convert.subscriptionLink(incentive.subscriptionLink)
} catch (error) {
// Note: cette erreur ne s'affiche que si la variable STOP_ON_INVALID_INPUT est vraie
console.error("Echec de la conversion de l'aide " + incentive.title + ", " + error)
incentive.title = ""
} finally {
return incentive
}
})
// Les aides sans titres sont invalides, cela ne sert à rien de les envoyer
incentives = incentives.filter(e => e.title !== "")
if (!TEST_RUN_DO_NOT_SEND_TO_API) {
for (var i = 0; i < incentives.length; i++) {
// Chaque aide est envoyée à l'API
sendReq(incentives[i])
}
}
});
// Simple appel à l'API
function sendReq(data) {
var options = {
'method': 'POST',
'url': API_URL,
'headers': {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer ' + API_TOKEN
},
body: JSON.stringify(data)
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
}