-
Notifications
You must be signed in to change notification settings - Fork 105
/
import.js
187 lines (159 loc) · 6.3 KB
/
import.js
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
187
const db = require('../../lib/db');
const util = require('../../lib/util');
const Fiscal = require('../finance/fiscal');
const { flux } = require('../../config/constants');
const central = require('./central');
const { updateQuantityInStockAfterMovement } = require('../stock');
exports.loadData = loadData;
// Perfoms actions based on project and form id
async function loadData(req, res, next) {
const { formId } = req.params;
const projectId = process.env.ODK_CENTRAL_PROJECT_ID;
const mapActions = {
pcima_pv_reception : loadFosaData,
};
try {
const data = await mapActions[formId](projectId, formId, req.session);
res.status(200).json(data);
} catch (error) {
next(error);
}
}
// fetch all depots
async function fetchAllDepots() {
return db.exec('SELECT uuid, BUID(uuid) hrUuid, text FROM depot;');
}
// fetch all lots
async function fetchAllLots() {
const query = `
SELECT uuid, BUID(uuid) hr_uuid, unit_cost, BUID(inventory_uuid) inventory_uuid, label, description FROM lot;
`;
return db.exec(query);
}
// fetch all movements
async function fetchAllMovements() {
const query = `
SELECT
document_uuid, depot_uuid, BUID(depot_uuid) hr_depot_uuid,
entity_uuid, BUID(entity_uuid) hr_entity_uuid,
lot_uuid, BUID(lot_uuid) hr_lot_uuid, is_exit
FROM stock_movement;
`;
return db.exec(query);
}
/**
* Import stock movements from odk
*/
async function loadFosaData(projectId, formId, session) {
const submissions = await central.submissions(projectId, formId);
const values = submissions.value;
const processed = [];
const transaction = db.transaction();
// MINIMIZE ALL FETCHING DATA FROM DB FUNCTIONS IN LOOP
// extract data for not using call to database in loop
// all good alternative for not crashing the server on error are welcome
const allDepots = await fetchAllDepots();
const allLots = await fetchAllLots();
const allMovements = await fetchAllMovements();
const updateStockData = [];
const inventoryUuids = [];
// extract periods from loop
// const periods = values.map(async line => {
// const period = {};
// period[line.date] = await Fiscal.lookupFiscalYearByDate(line.date);
// return period;
// });
// CLEAN ALL PREVIOUS IMPORTED DATA
await db.exec('DELETE FROM stock_movement WHERE description LIKE "[ODK] RECEPTION FOSA"');
// process each line as a separated document
values.forEach(async line => {
let depotPattern;
const operationDate = new Date(line.date);
const destination = line.depot_destination;
const depotType = String(destination.depot_type_destination).toUpperCase();
const depotName = destination.structure_coallesced;
const depotZone = destination.health_zone;
const depotArea = destination.health_area;
const depotZoneArea = `(${depotZone}/${depotArea})`;
if (depotType === 'FOSA') {
depotPattern = `${depotType} - ${depotName} ${depotZoneArea}`;
} else if (depotType === 'BCZ') {
depotPattern = `${depotType} - ${depotZone}`;
} else if (depotType === 'CDR') {
depotPattern = `${depotType} - ${destination.cdr}`;
}
// look for the depot
const qDepot = allDepots.filter(depot => depot.text === depotPattern);
const depotUuid = qDepot.length ? qDepot[0].uuid : undefined;
const depotHrUuid = qDepot.length ? qDepot[0].hrUuid : undefined;
// get the fiscal year period information
const period = await Fiscal.lookupFiscalYearByDate(line.date);
const lots = line.boite_barcode_repeat.map(lot => {
return {
barcode : lot.boite_barcode,
batchNumber : lot.boite_batch_number,
expirationDate : lot.boite_expiration_date,
produit : lot.boite_produit,
date : new Date(line.date),
typeDestination : destination.depot_type_destination,
healthZone : destination.health_zone,
healthArea : destination.health_area,
structure : destination.structure_coallesced,
cdr : destination.cdr,
};
});
lots.forEach(async item => {
const qLot = allLots.filter(lot => lot.label === item.barcode && lot.description === item.batchNumber);
const lotUuid = qLot.length ? qLot[0].uuid : undefined;
const lotHrUuid = qLot.length ? qLot[0].hr_uuid : undefined;
const lotUnitCost = qLot.length ? qLot[0].unit_cost : undefined;
const inventoryUuid = qLot.length ? qLot[0].inventory_uuid : undefined;
const qOrigin = allMovements
.filter(mov => +mov.is_exit === 1 && mov.hr_lot_uuid === lotHrUuid && mov.hr_entity_uuid === depotHrUuid);
const originDocumentUuid = qOrigin.length ? qOrigin[0].document_uuid : undefined;
const originDepotUuid = qOrigin.length ? qOrigin[0].depot_uuid : undefined;
// make sure there was a stock exit in bhima for this entry from odk
if (depotUuid && originDocumentUuid) {
const record = {
depot_uuid : depotUuid,
entity_uuid : originDepotUuid,
is_exit : 0,
flux_id : flux.FROM_OTHER_DEPOT,
uuid : db.bid(util.uuid()),
lot_uuid : lotUuid,
document_uuid : originDocumentUuid,
quantity : 1,
unit_cost : lotUnitCost,
date : operationDate,
description : '[ODK] RECEPTION FOSA',
user_id : session.user.id,
period_id : period.id,
};
transaction.addQuery('INSERT INTO stock_movement SET ?', [record]);
processed.push(item);
// gather inventory uuids for later quantity in stock calculation updates
inventoryUuids.push(inventoryUuid);
}
});
// update the quantity in stock as needed
if (inventoryUuids.length) {
const uniqueInventoryUuids = inventoryUuids.filter((item, index, arr) => arr.indexOf(item) === index);
const dataToUpdate = {
inventories : uniqueInventoryUuids,
date : operationDate,
depot : depotHrUuid,
};
updateStockData.push(dataToUpdate);
// add transaction to recompute stock value
transaction.addQuery('CALL RecomputeStockValue(NULL);');
}
});
// execute the movement
await transaction.execute();
// update stock quantities
const dbPromise = updateStockData
.map(data => updateQuantityInStockAfterMovement(data.inventories, data.date, data.depot));
await Promise.all(dbPromise);
// for the client
return processed;
}