Skip to content

Commit

Permalink
feat: add odk_central_integration tables
Browse files Browse the repository at this point in the history
Adds odk central integration tables for the eventual link to ODK
Central.  Currently adds them under Stock Settings, but we can move them
easily enough later.

Related to Third-Culture-Software#6235.
  • Loading branch information
jniles authored and mbayopanda committed Jan 24, 2022
1 parent 61805b7 commit 2b8b850
Show file tree
Hide file tree
Showing 13 changed files with 694 additions and 420 deletions.
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ ENV YARN_VERSION 1.22.17
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD 1
RUN yarn policies set-version $YARN_VERSION
ENV CHROME_BIN /usr/bin/chromium
ENV PUPPETEER_EXECUTABLE_PATH /usr/bin/chromium

# define working directory inside the container
WORKDIR /usr/src/app
Expand Down
11 changes: 11 additions & 0 deletions client/src/i18n/en/odk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"ODK" : {
"LOAD_FOSA_DATA" : "Load data of FOSA",
"TOTAL_FOUND" : "Total records found",
"NO_RECORD_FOUND" : "No record found",
"IMPORTED_SUCCESSFULLY" : "Records successfully imported",
"ODK_CENTRAL_URL" : "ODK Central Server URL",
"ODK_ADMIN_USER" : "ODK Central Admin Email",
"ODK_ADMIN_PASSWORD" : "ODK Central Admin Password"
}
}
4 changes: 4 additions & 0 deletions client/src/i18n/en/stock.json
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,10 @@
"TOGGLE_EXPIRY_RISKS_HELP_TEXT" : "This will display the lots at risk, whose average monthly consumption will not allow total consumption before the expiration date."
},
"SETTINGS" : {
"CONSUMPTION_AND_REORDER_SETTINGS" : "Stock Consumption and Reorder Settings",
"ACCOUNTING_INTEGRATION_SETTINGS" : "Stock Accounting Integration",
"ODK_INTEGRATION_SETTINGS" : "ODK Integration Settings",
"OTHER_SETTINGS" : "Other Settings",
"DEFAULT_MIN_MONTHS_SECURITY_STOCK": "Default minimum number of months of security stock for depots",
"DEFAULT_MIN_MONTHS_SECURITY_STOCK_HELP_TEXT": "The stock supply should provide at least this many months of stock for the depot involved.",
"DEFAULT_PURCHASE_ORDER_INTERVAL" : "Default Purchase order interval (In Month)",
Expand Down
11 changes: 11 additions & 0 deletions client/src/i18n/fr/odk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"ODK" : {
"LOAD_FOSA_DATA" : "Chargement des données des FOSA",
"TOTAL_FOUND" : "Total des enregistrements trouvés",
"NO_RECORD_FOUND" : "Aucun enregistrement trouvé",
"IMPORTED_SUCCESSFULLY" : "Données importées avec succès",
"ODK_CENTRAL_URL" : "URL du serveur ODK Central",
"ODK_ADMIN_USER" : "Adressse mail de l'administrateur",
"ODK_ADMIN_PASSWORD" : "Mot de passe de l'administrateur"
}
}
4 changes: 4 additions & 0 deletions client/src/i18n/fr/stock.json
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,10 @@
"TOGGLE_EXPIRY_RISKS_HELP_TEXT" : "Ceci permettra d'afficher les lots à risque, dont la consommation moyenne mensuel ne permettra pas la consommation total avant la date de peremption"
},
"SETTINGS" : {
"CONSUMPTION_AND_REORDER_SETTINGS" : "Consommation de stock et de réapprovisionnement",
"ACCOUNTING_INTEGRATION_SETTINGS" : "Intégration de la comptabilité des stocks",
"ODK_INTEGRATION_SETTINGS" : "Paramètres d'intégration ODK",
"OTHER_SETTINGS" : "Autres paramètres",
"DEFAULT_MIN_MONTHS_SECURITY_STOCK": "Nombre minimum de mois par défaut de stock de sécurité pour les dépôts",
"DEFAULT_MIN_MONTHS_SECURITY_STOCK_HELP_TEXT": "L'approvisionnement en stock devrait fournir au moins ce nombre de mois de stock pour le dépôt concerné.",
"DEFAULT_PURCHASE_ORDER_INTERVAL" : "Intervalle de commande par défaut (En mois)",
Expand Down
379 changes: 228 additions & 151 deletions client/src/modules/stock/settings/stock-settings.html

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion client/src/modules/stock/settings/stock-settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function StockSettingsController(
const vm = this;

vm.enterprise = {};
vm.settings = {};
vm.settings = { odk : {} };

let $touched = false;

Expand All @@ -41,6 +41,8 @@ function StockSettingsController(
if (settings.length > 0) {
[vm.settings] = settings;
}

console.log('settings:', settings);
})
.catch(Notify.handleError);

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@
"jeremielodi"
],
"dependencies": {
"@ima-worldhealth/coral": "^2.9.2",
"@ima-worldhealth/coral": "^2.9.0",
"@ima-worldhealth/odk-central-api": "^1.2.1",
"@ima-worldhealth/tree": "^2.5.1",
"@types/angular": "^1.8.4",
"@uirouter/angularjs": "^1.0.29",
Expand Down
3 changes: 3 additions & 0 deletions server/controllers/admin/odk-central.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const central = import('@ima-worldhealth/odk-central-api');


99 changes: 67 additions & 32 deletions server/controllers/stock/setting/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,22 @@
const db = require('../../../lib/db');
const NotFound = require('../../../lib/errors/NotFound');


let central;

// because the ODK Central API is ESM, we must use a dynamic import()
// instead of require().
(async () => {
central = await import('@ima-worldhealth/odk-central-api');
})();

// GET /stock/setting
//
// Get the current stock settings for the Enterprise
// If req.query.enterprise_id is set, it will use that,
// otherwise it will look up the entry for Enterprise.id=1
exports.list = function list(req, res, next) {
let enterpriseId = req.session.enterprise.id;
if (req.params.id) {
// If the enterprise was passed in as a parameter, use it
enterpriseId = req.params.id;
}
exports.list = async function list(req, res, next) {
const enterpriseId = req.params.id || req.session.enterprise.id;

const sql = `
SELECT month_average_consumption, default_min_months_security_stock,
Expand All @@ -30,39 +35,69 @@ exports.list = function list(req, res, next) {
WHERE enterprise_id = ? LIMIT 1;
`;

db.exec(sql, [enterpriseId])
.then(rows => {
if (rows.length === 1) {
res.status(200).json(rows);
} else {
throw new NotFound(`Could not find stock_setting data with enterprise id ${req.params.id} (get)`);
}

})
.catch(next)
.done();
try {
const rows = await db.exec(sql, [enterpriseId]);

if (rows.length !== 1) {
throw new NotFound(`Could not find stock_setting data with enterprise id ${req.params.id} (get)`);
}

const [settings] = rows;

const odkSettings = await db.exec('SELECT * FROM odk_central_integration WHERE enterprise_id = ?;', [enterpriseId]);

// merge in the settings if they are defined
if (odkSettings.length > 0) {
settings.odk = odkSettings.pop();
}

res.status(200).json([settings]);
} catch (e) {
next(e);
}
};

// PUT /stock/setting/:id
//
// Update the settings in stock_settings for the settings
// with enterprise_id given by the 'id' parameter
exports.update = function update(req, res, next) {
exports.update = async function update(req, res, next) {
const sql = 'UPDATE stock_setting SET ? WHERE enterprise_id = ?';
const { settings } = req.body;
const { odk } = settings;

delete settings.odk;

db.exec(sql, [settings, req.params.id])
.then((row) => {
if (!row.affectedRows) {
throw new NotFound(`Could not find stock_setting row with enterprise id ${req.params.id} (put)`);
}
// Get the updated values
return db.exec('UPDATE stock_setting SET ? WHERE enterprise_id = ?',
[settings, req.params.id]);
})
.then((updatedSettings) => {
res.status(200).json(updatedSettings);
})
.catch(next)
.done();
try {

const { affectedRows } = await db.exec(sql, [settings, req.params.id]);

if (!affectedRows) {
throw new NotFound(`Could not find stock_setting row with enterprise id ${req.params.id} (put)`);
}

const updatedSettings = await db.exec(
'UPDATE stock_setting SET ? WHERE enterprise_id = ?',
[settings, req.params.id]);

// update the ODK settings
if (odk) {
await db.exec('DELETE FROM odk_central_integration WHERE enterprise_id = ?', [req.params.id]);
await db.exec('INSERT INTO odk_central_integration SET ?;', [{ ...odk, enterprise_id : req.params.id }]);

// attempt to log in with the ODK api
await setupODKCentralConnection(odk.odk_central_url, odk.odk_admin_user, odk.odk_admin_password);
}

res.status(200).json(updatedSettings);
} catch (e) {
next(e);
}
};

async function setupODKCentralConnection(serverUrl, userEmail, userPassword) {
central.auth.setConfig(serverUrl, userEmail, userPassword);

const details = await central.api.users.getCurrentUserDetails();

}
15 changes: 15 additions & 0 deletions server/models/migrations/next/migrate.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* migration file for next release */

ALTER TABLE `enterprise_setting` ADD COLUMN `enable_odk_central_integration` BOOLEAN NOT NULL DEFAULT FALSE;


DROP TABLE IF EXISTS `odk_central_integration`;
CREATE TABLE `odk_central_integration` (
`enterprise_id` SMALLINT(5) UNSIGNED NOT NULL,
`odk_central_url` TEXT NOT NULL,
`odk_admin_user` TEXT NOT NULL,
`odk_admin_password` TEXT NOT NULL,
`odk_project_id` INTEGER UNSIGNED NULL,
KEY `enterprise_id` (`enterprise_id`),
CONSTRAINT `odk_central__enterprise` FOREIGN KEY (`enterprise_id`) REFERENCES `enterprise` (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET = utf8mb4 DEFAULT COLLATE = utf8mb4_unicode_ci;
12 changes: 12 additions & 0 deletions server/models/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,7 @@ CREATE TABLE `enterprise_setting` (
`base_index_growth_rate` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0,
`posting_payroll_cost_center_mode` VARCHAR(100) NOT NULL DEFAULT 'default', -- With this function, transactions related to employee payment are done in bulk and require that each expense account be linked to a cost center
`enable_require_cost_center_for_posting` TINYINT(1) NOT NULL DEFAULT 0,
`enable_odk_central_integration` BOOLEAN NOT NULL DEFAULT FALSE,
PRIMARY KEY (`enterprise_id`),
CONSTRAINT `enterprise_setting__enterprise` FOREIGN KEY (`enterprise_id`) REFERENCES `enterprise` (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET = utf8mb4 DEFAULT COLLATE = utf8mb4_unicode_ci;
Expand Down Expand Up @@ -2633,4 +2634,15 @@ CREATE TABLE `cost_center_aggregate` (
CONSTRAINT `cost_center_aggregate__cost_center_id` FOREIGN KEY (`cost_center_id`) REFERENCES `cost_center` (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET = utf8mb4 DEFAULT COLLATE = utf8mb4_unicode_ci;

DROP TABLE IF EXISTS `odk_central_integration`;
CREATE TABLE `odk_central_integration` (
`enterprise_id` SMALLINT(5) UNSIGNED NOT NULL,
`odk_central_url` TEXT NOT NULL,
`odk_admin_user` TEXT NOT NULL,
`odk_admin_password` TEXT NOT NULL,
`odk_project_id` INTEGER UNSIGNED NULL,
KEY `enterprise_id` (`enterprise_id`),
CONSTRAINT `odk_central__enterprise` FOREIGN KEY (`enterprise_id`) REFERENCES `enterprise` (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET = utf8mb4 DEFAULT COLLATE = utf8mb4_unicode_ci;

SET foreign_key_checks = 1;
Loading

0 comments on commit 2b8b850

Please sign in to comment.