diff --git a/client/src/i18n/en/report.json b/client/src/i18n/en/report.json
index a00e38b396..d79448c2ae 100644
--- a/client/src/i18n/en/report.json
+++ b/client/src/i18n/en/report.json
@@ -177,7 +177,13 @@
"INCLUDE_SERVICE_EXIT": "Include stock exit to service",
"INCLUDE_DEPOT_EXIT": "Include stock exit to other depots",
"INCLUDE_LOSS_EXIT": "Include stock loss",
- "SHOW_DETAILS": "Show Details"
+ "SHOW_DETAILS": "Show Details",
+ "ENTRY_REPORT": "Stock Entry Report",
+ "ENTRY_REPORT_DESCRIPTION": "This report displays the different stock entries that took place in depots",
+ "INCLUDE_PURCHASE_ENTRY": "Include entries from purchases",
+ "INCLUDE_INTEGRATION_ENTRY": "Include entries from integrations",
+ "INCLUDE_DONATION_ENTRY": "Include entries from donation",
+ "INCLUDE_TRANSFER_ENTRY": "Include entries from transfers"
},
"UTIL": {
"CANCEL_PREVIEW": "Cancel Preview",
diff --git a/client/src/i18n/en/tree.json b/client/src/i18n/en/tree.json
index 529729e698..693943b850 100644
--- a/client/src/i18n/en/tree.json
+++ b/client/src/i18n/en/tree.json
@@ -116,6 +116,7 @@
"STOCK_REPORT" : "[Stock] Inventories",
"STOCK_INVENTORY_REPORT" : "[Stock] Inventory Report",
"STOCK_EXIT_REPORT" : "[Stock] Exit Report",
+ "STOCK_ENTRY_REPORT":"[Stock] Entries Report",
"STOCK_LOTS" : "Stock Lots",
"STOCK_VALUE" : "[Stock] Stock value Report",
"STOCK_MOVEMENTS" : "Stock Movements",
diff --git a/client/src/i18n/fr/report.json b/client/src/i18n/fr/report.json
index 3923af732c..246d5b2db6 100644
--- a/client/src/i18n/fr/report.json
+++ b/client/src/i18n/fr/report.json
@@ -177,7 +177,13 @@
"INCLUDE_SERVICE_EXIT" : "Inclure les distributions vers les services",
"INCLUDE_DEPOT_EXIT" : "Inclure les distributions vers d'autres dépôts",
"INCLUDE_LOSS_EXIT" : "Inclure les pertes de stocks",
- "SHOW_DETAILS" : "Afficher les details"
+ "SHOW_DETAILS" : "Afficher les details",
+ "ENTRY_REPORT": "Rapports des entrées de stocks",
+ "ENTRY_REPORT_DESCRIPTION": "Ce rapport affiche les différentes entrées de stock qui ont eu lieu dans les dépots",
+ "INCLUDE_PURCHASE_ENTRY": "Inclure les entrées en provenance des achats",
+ "INCLUDE_INTEGRATION_ENTRY": "Inclure les entrées en provenance des intégrations",
+ "INCLUDE_DONATION_ENTRY": "Inclure les entrées en provenance des donations",
+ "INCLUDE_TRANSFER_ENTRY": "Inclure les entrées en provenance des transferts"
},
"UTIL":{
"CANCEL_PREVIEW" : "Fermer l'Aperçu",
diff --git a/client/src/i18n/fr/stock.json b/client/src/i18n/fr/stock.json
index 71aa8b1029..d2515464a2 100644
--- a/client/src/i18n/fr/stock.json
+++ b/client/src/i18n/fr/stock.json
@@ -109,7 +109,7 @@
"TRANSFER_AVAILABLE" : "Disponible",
"RECEIPT" : {
"ADJUSTMENT" : "Ajustement",
- "ENTRY_DEPOT" : "Entrée de Stock",
+ "ENTRY_DEPOT" : "Entrée en provenance d'autres dépots",
"ENTRY_DONATION" : "Entree de Stock - Donation",
"ENTRY_PURCHASE" : "Entree de Stock - Achat",
"ENTRY_INTEGRATION" : "Entree de Stock - Intégration",
diff --git a/client/src/i18n/fr/tree.json b/client/src/i18n/fr/tree.json
index 1f1eb9a7ec..80da5d88bc 100644
--- a/client/src/i18n/fr/tree.json
+++ b/client/src/i18n/fr/tree.json
@@ -115,7 +115,8 @@
"STOCK_INVENTORY":"Articles en stock",
"STOCK_REPORT": "[Stock] Articles en stock",
"STOCK_INVENTORY_REPORT":"[Stock] Fiche de stock",
- "STOCK_EXIT_REPORT":"[Stock] Sortie des stocks",
+ "STOCK_EXIT_REPORT":"[Stock] Sorties des stocks",
+ "STOCK_ENTRY_REPORT":"[Stock] Entrées des stocks",
"STOCK_LOTS":"Lots en stock",
"STOCK_VALUE" : "[Stock] Valeur de stock",
"STOCK_MOVEMENTS":"Movements de stock",
diff --git a/client/src/modules/reports/generate/stock_entry/stock_entry.config.js b/client/src/modules/reports/generate/stock_entry/stock_entry.config.js
new file mode 100644
index 0000000000..237ab187f2
--- /dev/null
+++ b/client/src/modules/reports/generate/stock_entry/stock_entry.config.js
@@ -0,0 +1,87 @@
+angular.module('bhima.controllers')
+ .controller('stock_entryController', StockEntryConfigController);
+
+StockEntryConfigController.$inject = [
+ '$sce', 'NotifyService', 'BaseReportService', 'AppCache', 'reportData', '$state',
+ 'LanguageService',
+];
+
+function StockEntryConfigController($sce, Notify, SavedReports, AppCache, reportData, $state, Languages) {
+ const vm = this;
+ const cache = new AppCache('configure_stock_entry_report');
+ const reportUrl = 'reports/stock/entry';
+
+ // default values
+ vm.reportDetails = {
+ includePurchaseEntry : 1,
+ };
+ vm.previewGenerated = false;
+ vm.onEntryTypeChange = onEntryTypeChange;
+
+ // check cached configuration
+ checkCachedConfiguration();
+
+ // check checked entry type
+ onEntryTypeChange();
+
+ vm.onSelectDepot = depot => {
+ vm.reportDetails.depotUuid = depot.uuid;
+ };
+
+ vm.clear = key => {
+ delete vm[key];
+ };
+
+ vm.clearPreview = () => {
+ vm.previewGenerated = false;
+ vm.previewResult = null;
+ };
+
+ vm.preview = form => {
+ if (form.$invalid) {
+ return 0;
+ }
+
+ if (!vm.hasOneChecked) {
+ return 0;
+ }
+
+ // update cached configuration
+ cache.reportDetails = angular.copy(vm.reportDetails);
+ angular.extend(vm.reportDetails, { lang : Languages.key });
+
+ return SavedReports.requestPreview(reportUrl, reportData.id, angular.copy(vm.reportDetails))
+ .then((result) => {
+ vm.previewGenerated = true;
+ vm.previewResult = $sce.trustAsHtml(result);
+ })
+ .catch(Notify.handleError);
+ };
+
+ vm.requestSaveAs = function requestSaveAs() {
+ const options = {
+ url : reportUrl,
+ report : reportData,
+ reportOptions : angular.copy(vm.reportDetails),
+ };
+
+ return SavedReports.saveAsModal(options)
+ .then(() => {
+ $state.go('reportsBase.reportsArchive', { key : options.report.report_key });
+ })
+ .catch(Notify.handleError);
+ };
+
+ function checkCachedConfiguration() {
+ vm.reportDetails = angular.copy(cache.reportDetails || {});
+ }
+
+ function onEntryTypeChange() {
+ // be sure at least one checkbox is checked
+ const sum = vm.reportDetails.includePurchaseEntry
+ + vm.reportDetails.includeIntegrationEntry
+ + vm.reportDetails.includeDonationEntry
+ + vm.reportDetails.includeTransferEntry;
+ vm.hasOneChecked = sum > 0;
+ }
+}
diff --git a/client/src/modules/reports/generate/stock_entry/stock_entry.html b/client/src/modules/reports/generate/stock_entry/stock_entry.html
new file mode 100644
index 0000000000..7b92a85eac
--- /dev/null
+++ b/client/src/modules/reports/generate/stock_entry/stock_entry.html
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
REPORT.STOCK.ENTRY_REPORT
+
REPORT.STOCK.ENTRY_REPORT_DESCRIPTION
+
+
+
+
+
+
+
+ REPORT.UTIL.OPTIONS
+
+
+
+
+
+
+
diff --git a/client/src/modules/reports/reports.routes.js b/client/src/modules/reports/reports.routes.js
index f9f2661b86..6d95f7c7b1 100644
--- a/client/src/modules/reports/reports.routes.js
+++ b/client/src/modules/reports/reports.routes.js
@@ -27,6 +27,7 @@ angular.module('bhima.routes')
'operating',
'patientStanding',
'stock_exit',
+ 'stock_entry',
'stock_value',
'unpaid-invoice-payments',
'breakEven',
diff --git a/server/config/routes.js b/server/config/routes.js
index a073c396b2..c8f6ea0d86 100644
--- a/server/config/routes.js
+++ b/server/config/routes.js
@@ -757,6 +757,7 @@ exports.configure = function configure(app) {
// stock reports API
app.get('/reports/stock/exit', stockReports.stockExitReport);
+ app.get('/reports/stock/entry', stockReports.stockEntryReport);
app.get('/reports/stock/lots', stockReports.stockLotsReport);
app.get('/reports/stock/movements', stockReports.stockMovementsReport);
app.get('/reports/stock/inventories', stockReports.stockInventoriesReport);
diff --git a/server/controllers/stock/reports/common.js b/server/controllers/stock/reports/common.js
index 08a2db2262..2540c922b2 100644
--- a/server/controllers/stock/reports/common.js
+++ b/server/controllers/stock/reports/common.js
@@ -16,6 +16,7 @@ const STOCK_ADJUSTMENT_TEMPLATE = `${BASE_PATH}/stock_adjustment.receipt.handleb
// reports
const STOCK_EXIT_REPORT_TEMPLATE = `${BASE_PATH}/stock_exit.report.handlebars`;
+const STOCK_ENTRY_REPORT_TEMPLATE = `${BASE_PATH}/stock_entry.report.handlebars`;
const STOCK_LOTS_REPORT_TEMPLATE = `${BASE_PATH}/stock_lots.report.handlebars`;
const STOCK_MOVEMENTS_REPORT_TEMPLATE = `${BASE_PATH}/stock_movements.report.handlebars`;
const STOCK_INVENTORIES_REPORT_TEMPLATE = `${BASE_PATH}/stock_inventories.report.handlebars`;
@@ -198,6 +199,7 @@ exports.STOCK_ENTRY_DONATION_TEMPLATE = STOCK_ENTRY_DONATION_TEMPLATE;
exports.STOCK_ADJUSTMENT_TEMPLATE = STOCK_ADJUSTMENT_TEMPLATE;
exports.STOCK_EXIT_REPORT_TEMPLATE = STOCK_EXIT_REPORT_TEMPLATE;
+exports.STOCK_ENTRY_REPORT_TEMPLATE = STOCK_ENTRY_REPORT_TEMPLATE;
exports.STOCK_LOTS_REPORT_TEMPLATE = STOCK_LOTS_REPORT_TEMPLATE;
exports.STOCK_MOVEMENTS_REPORT_TEMPLATE = STOCK_MOVEMENTS_REPORT_TEMPLATE;
exports.STOCK_INVENTORY_REPORT_TEMPLATE = STOCK_INVENTORY_REPORT_TEMPLATE;
diff --git a/server/controllers/stock/reports/index.js b/server/controllers/stock/reports/index.js
index 9522a084c8..60a7b7002a 100644
--- a/server/controllers/stock/reports/index.js
+++ b/server/controllers/stock/reports/index.js
@@ -8,6 +8,7 @@
*/
const stockExitReport = require('./stock/exit_report');
+const stockEntryReport = require('./stock/entry_report');
const stockLotsReport = require('./stock/lots_report');
const stockMovementsReport = require('./stock/movements_report');
const stockInventoriesReport = require('./stock/inventories_report');
@@ -26,6 +27,7 @@ const stockAssignReceipt = require('./stock/assign_receipt');
// expose to the api
exports.stockExitReport = stockExitReport;
+exports.stockEntryReport = stockEntryReport;
exports.stockLotsReport = stockLotsReport;
exports.stockMovementsReport = stockMovementsReport;
exports.stockInventoriesReport = stockInventoriesReport;
diff --git a/server/controllers/stock/reports/stock/entry/entryFromDonation.js b/server/controllers/stock/reports/stock/entry/entryFromDonation.js
new file mode 100644
index 0000000000..bd67eb4f58
--- /dev/null
+++ b/server/controllers/stock/reports/stock/entry/entryFromDonation.js
@@ -0,0 +1,38 @@
+const db = require('../../../../../lib/db');
+
+const IS_EXIT = 0;
+const ENTRY_FROM_DONATION_ID = 6;
+
+/**
+ * @function fetch
+ * @description fetch stock entry from donation
+ */
+function fetch(depotUuid, dateFrom, dateTo, showDetails) {
+ const sql = `
+ SELECT
+ i.code, i.text, iu.text AS unit_text, BUID(m.document_uuid) AS document_uuid,
+ SUM(m.quantity) as quantity, m.date, m.description,
+ u.display_name AS user_display_name,
+ dm.text AS document_reference, d.text AS depot_name
+ FROM stock_movement m
+ JOIN lot l ON l.uuid = m.lot_uuid
+ JOIN inventory i ON i.uuid = l.inventory_uuid
+ JOIN inventory_unit iu ON iu.id = i.unit_id
+ JOIN depot d ON d.uuid = m.depot_uuid
+ JOIN user u ON u.id = m.user_id
+ LEFT JOIN document_map dm ON dm.uuid = m.document_uuid
+ WHERE m.is_exit = ${IS_EXIT} AND m.flux_id = ${ENTRY_FROM_DONATION_ID} AND d.uuid = ?
+ AND (DATE(m.date) BETWEEN DATE(?) AND DATE(?))
+ GROUP BY i.uuid`;
+
+ const groupBy = ', m.uuid';
+ const orderBy = ' ORDER BY i.text, m.date ASC';
+ const query = showDetails ? sql.concat(groupBy, orderBy) : sql.concat(orderBy);
+
+ const _depotUuid = db.bid(depotUuid);
+ const _dateFrom = new Date(dateFrom);
+ const _dateTo = new Date(dateTo);
+ return db.exec(query, [_depotUuid, _dateFrom, _dateTo]);
+}
+
+module.exports.fetch = fetch;
diff --git a/server/controllers/stock/reports/stock/entry/entryFromIntegration.js b/server/controllers/stock/reports/stock/entry/entryFromIntegration.js
new file mode 100644
index 0000000000..af49b86786
--- /dev/null
+++ b/server/controllers/stock/reports/stock/entry/entryFromIntegration.js
@@ -0,0 +1,38 @@
+const db = require('../../../../../lib/db');
+
+const IS_EXIT = 0;
+const ENTRY_FROM_INTEGRATION_ID = 13;
+
+/**
+ * @function fetch
+ * @description fetch stock entry from integration
+ */
+function fetch(depotUuid, dateFrom, dateTo, showDetails) {
+ const sql = `
+ SELECT
+ i.code, i.text, iu.text AS unit_text, BUID(m.document_uuid) AS document_uuid,
+ SUM(m.quantity) as quantity, m.date, m.description,
+ u.display_name AS user_display_name,
+ dm.text AS document_reference, d.text AS depot_name
+ FROM stock_movement m
+ JOIN lot l ON l.uuid = m.lot_uuid
+ JOIN inventory i ON i.uuid = l.inventory_uuid
+ JOIN inventory_unit iu ON iu.id = i.unit_id
+ JOIN depot d ON d.uuid = m.depot_uuid
+ JOIN user u ON u.id = m.user_id
+ LEFT JOIN document_map dm ON dm.uuid = m.document_uuid
+ WHERE m.is_exit = ${IS_EXIT} AND m.flux_id = ${ENTRY_FROM_INTEGRATION_ID} AND d.uuid = ?
+ AND (DATE(m.date) BETWEEN DATE(?) AND DATE(?))
+ GROUP BY i.uuid`;
+
+ const groupBy = ', m.uuid';
+ const orderBy = ' ORDER BY i.text, m.date ASC';
+ const query = showDetails ? sql.concat(groupBy, orderBy) : sql.concat(orderBy);
+
+ const _depotUuid = db.bid(depotUuid);
+ const _dateFrom = new Date(dateFrom);
+ const _dateTo = new Date(dateTo);
+ return db.exec(query, [_depotUuid, _dateFrom, _dateTo]);
+}
+
+module.exports.fetch = fetch;
diff --git a/server/controllers/stock/reports/stock/entry/entryFromPurchase.js b/server/controllers/stock/reports/stock/entry/entryFromPurchase.js
new file mode 100644
index 0000000000..d379b8262a
--- /dev/null
+++ b/server/controllers/stock/reports/stock/entry/entryFromPurchase.js
@@ -0,0 +1,43 @@
+const db = require('../../../../../lib/db');
+
+const IS_EXIT = 0;
+const ENTRY_FROM_PURCHASE_ID = 1;
+
+/**
+ * @function fetch
+ * @description fetch stock entry from purchase
+ */
+function fetch(depotUuid, dateFrom, dateTo, showDetails) {
+ const sql = `
+ SELECT
+ i.code, i.text, iu.text AS unit_text, BUID(m.document_uuid) AS document_uuid,
+ SUM(m.quantity) as quantity, m.date, m.description,
+ u.display_name AS user_display_name, sup.display_name AS supplier_display_name,
+ dm.text AS document_reference, d.text AS depot_name,
+ dm2.text AS purchase_reference
+ FROM stock_movement m
+ JOIN lot l ON l.uuid = m.lot_uuid
+ JOIN inventory i ON i.uuid = l.inventory_uuid
+ JOIN inventory_unit iu ON iu.id = i.unit_id
+ JOIN depot d ON d.uuid = m.depot_uuid
+ JOIN purchase p ON p.uuid = l.origin_uuid
+ JOIN supplier sup ON sup.uuid = p.supplier_uuid
+ JOIN project proj ON proj.id = p.project_id
+ JOIN user u ON u.id = m.user_id
+ LEFT JOIN document_map dm ON dm.uuid = m.document_uuid
+ LEFT JOIN document_map dm2 ON dm2.uuid = p.uuid
+ WHERE m.is_exit = ${IS_EXIT} AND m.flux_id = ${ENTRY_FROM_PURCHASE_ID} AND d.uuid = ?
+ AND (DATE(m.date) BETWEEN DATE(?) AND DATE(?))
+ GROUP BY i.uuid`;
+
+ const groupBy = ', m.uuid, p.uuid';
+ const orderBy = ' ORDER BY i.text, m.date ASC';
+ const query = showDetails ? sql.concat(groupBy, orderBy) : sql.concat(orderBy);
+
+ const _depotUuid = db.bid(depotUuid);
+ const _dateFrom = new Date(dateFrom);
+ const _dateTo = new Date(dateTo);
+ return db.exec(query, [_depotUuid, _dateFrom, _dateTo]);
+}
+
+module.exports.fetch = fetch;
diff --git a/server/controllers/stock/reports/stock/entry/entryFromTransfer.js b/server/controllers/stock/reports/stock/entry/entryFromTransfer.js
new file mode 100644
index 0000000000..420e8c5ba7
--- /dev/null
+++ b/server/controllers/stock/reports/stock/entry/entryFromTransfer.js
@@ -0,0 +1,39 @@
+const db = require('../../../../../lib/db');
+
+const IS_EXIT = 0;
+const ENTRY_FROM_DEPOT_ID = 2;
+
+/**
+ * @function fetch
+ * @description fetch stock entry from donation
+ */
+function fetch(depotUuid, dateFrom, dateTo, showDetails) {
+ const sql = `
+ SELECT
+ i.code, i.text, iu.text AS unit_text, BUID(m.document_uuid) AS document_uuid,
+ SUM(m.quantity) as quantity, m.date, m.description,
+ u.display_name AS user_display_name,
+ dm.text AS document_reference, dd.text AS depot_name
+ FROM stock_movement m
+ JOIN lot l ON l.uuid = m.lot_uuid
+ JOIN inventory i ON i.uuid = l.inventory_uuid
+ JOIN inventory_unit iu ON iu.id = i.unit_id
+ JOIN depot d ON d.uuid = m.depot_uuid
+ JOIN depot dd ON dd.uuid = m.entity_uuid
+ JOIN user u ON u.id = m.user_id
+ LEFT JOIN document_map dm ON dm.uuid = m.document_uuid
+ WHERE m.is_exit = ${IS_EXIT} AND m.flux_id = ${ENTRY_FROM_DEPOT_ID} AND d.uuid = ?
+ AND (DATE(m.date) BETWEEN DATE(?) AND DATE(?))
+ GROUP BY i.uuid`;
+
+ const groupBy = ', m.uuid, dd.uuid';
+ const orderBy = ' ORDER BY i.text, m.date ASC';
+ const query = showDetails ? sql.concat(groupBy, orderBy) : sql.concat(orderBy);
+
+ const _depotUuid = db.bid(depotUuid);
+ const _dateFrom = new Date(dateFrom);
+ const _dateTo = new Date(dateTo);
+ return db.exec(query, [_depotUuid, _dateFrom, _dateTo]);
+}
+
+module.exports.fetch = fetch;
diff --git a/server/controllers/stock/reports/stock/entry_report.js b/server/controllers/stock/reports/stock/entry_report.js
new file mode 100644
index 0000000000..50da07e77e
--- /dev/null
+++ b/server/controllers/stock/reports/stock/entry_report.js
@@ -0,0 +1,147 @@
+const {
+ _, db, util, ReportManager, pdfOptions, STOCK_ENTRY_REPORT_TEMPLATE,
+} = require('../common');
+
+const StockEntryFromPurchase = require('./entry/entryFromPurchase');
+const StockEntryFromIntegration = require('./entry/entryFromIntegration');
+const StockEntryFromDonation = require('./entry/entryFromDonation');
+const StockEntryFromTransfer = require('./entry/entryFromTransfer');
+
+/**
+ * @method stockEntryReport
+ *
+ * @description
+ * This method builds the stock entry report as either a JSON, PDF, or HTML
+ * file to be sent to the client.
+ *
+ * GET /reports/stock/entry
+ */
+function stockEntryReport(req, res, next) {
+ let report;
+
+ const params = util.convertStringToNumber(req.query);
+
+ const optionReport = _.extend(params, pdfOptions, {
+ filename : 'REPORT.STOCK.ENTRY_REPORT',
+ });
+
+ // set up the report with report manager
+ try {
+ report = new ReportManager(STOCK_ENTRY_REPORT_TEMPLATE, req.session, optionReport);
+ } catch (e) {
+ return next(e);
+ }
+
+ return fetchDepotDetails(params.depotUuid)
+ .then(depot => {
+ params.depotName = depot.text;
+ return collect(params);
+ })
+ .then(groupCollection)
+ .then((bundle) => {
+ _.extend(bundle, params);
+
+ return report.render(bundle);
+ })
+ .then((result) => {
+ res.set(result.headers).send(result.report);
+ })
+ .catch(next)
+ .done();
+}
+
+/**
+ * fetchDepotDetails
+ * @param {number} depotUuid depot uuid
+ */
+function fetchDepotDetails(depotUuid) {
+ const query = 'SELECT text FROM depot WHERE uuid = ?';
+ return db.one(query, [db.bid(depotUuid)]);
+}
+
+/**
+ * @function groupCollection
+ * @description group collected data by inventory
+ */
+function groupCollection(entryCollection) {
+ const collection = {};
+
+ // entry to purchase
+ collection.entryFromPurchase = formatAndCombine(entryCollection.entryFromPurchase);
+
+ // entry to integration
+ collection.entryFromIntegration = formatAndCombine(entryCollection.entryFromIntegration);
+
+ // entry to donation
+ collection.entryFromDonation = formatAndCombine(entryCollection.entryFromDonation);
+
+ // entry to transfer
+ collection.entryFromTransfer = formatAndCombine(entryCollection.entryFromTransfer);
+
+ return collection;
+}
+
+function formatAndCombine(data) {
+ const aggregate = _.chain(data)
+ .groupBy('text')
+ .map(formatEntry)
+ .value();
+
+ return { data : aggregate, isEmpty : _.size(aggregate) === 0 };
+}
+
+/**
+ * @function formatEntry
+ */
+function formatEntry(value, key) {
+ return {
+ inventory_name : key,
+ inventory_unit : value && value[0] ? value[0].unit_text : '',
+ inventory_stock_entry_data : value,
+ inventory_stock_entry_quantity : _.sumBy(value, 'quantity'),
+ };
+}
+
+/**
+ * @function collect
+ * @param {object} params query parameters
+ * @return {promise} { entryFromPurchase: [], entryFromIntegration: [], entryFromDonation: [], entryFromTransfer: [] }
+ */
+async function collect(params) {
+ const {
+ depotUuid,
+ dateFrom,
+ dateTo,
+ showDetails,
+ includePurchaseEntry,
+ includeIntegrationEntry,
+ includeDonationEntry,
+ includeTransferEntry,
+ } = params;
+
+ const data = {};
+
+ // get stock entry from purchase
+ if (includePurchaseEntry) {
+ data.entryFromPurchase = await StockEntryFromPurchase.fetch(depotUuid, dateFrom, dateTo, showDetails);
+ }
+
+ // get stock entry from integration
+ if (includeIntegrationEntry) {
+ data.entryFromIntegration = await StockEntryFromIntegration.fetch(depotUuid, dateFrom, dateTo, showDetails);
+ }
+
+ // get stock entry from donation
+ if (includeDonationEntry) {
+ data.entryFromDonation = await StockEntryFromDonation.fetch(depotUuid, dateFrom, dateTo, showDetails);
+ }
+
+ // get stock entry from transfer
+ if (includeTransferEntry) {
+ data.entryFromTransfer = await StockEntryFromTransfer.fetch(depotUuid, dateFrom, dateTo, showDetails);
+ }
+
+ return data;
+}
+
+module.exports = stockEntryReport;
diff --git a/server/controllers/stock/reports/stock_entry.report.handlebars b/server/controllers/stock/reports/stock_entry.report.handlebars
new file mode 100644
index 0000000000..762a2d9f4f
--- /dev/null
+++ b/server/controllers/stock/reports/stock_entry.report.handlebars
@@ -0,0 +1,216 @@
+{{> head title="REPORT.STOCK.ENTRY_REPORT" }}
+
+
+
+
+ {{> header}}
+
+
+
+
+
+
+
+ {{translate 'REPORT.STOCK.ENTRY_REPORT'}}
+
+
+
+ {{ depotName }}
+
+
+
+ {{date dateFrom}} - {{date dateTo}}
+
+
+
+
+
+ {{#if includePurchaseEntry}}
+
{{translate 'STOCK.RECEIPT.ENTRY_PURCHASE'}}
+
+
+ {{#each entryFromPurchase.data as | data |}}
+
+
+ {{ data.inventory_name }} |
+ {{ data.inventory_stock_entry_quantity }} ({{ data.inventory_unit }}) |
+
+
+
+ {{#if ../showDetails}}
+
+ {{#each data.inventory_stock_entry_data as | item |}}
+
+ {{ document_reference }} |
+ ({{ purchase_reference }}) {{ supplier_display_name }} |
+ |
+ {{date date }} |
+ {{ quantity }} ({{ unit_text }}) |
+
+ {{/each}}
+
+ {{/if}}
+
+ {{/each}}
+
+
+ {{#if entryFromPurchase.isEmpty}}
+ {{translate 'STOCK.NO_DATA'}} |
+ {{/if}}
+
+ {{/if}}
+
+
+
+
+ {{#if includeIntegrationEntry}}
+
{{translate 'STOCK.RECEIPT.ENTRY_INTEGRATION'}}
+
+
+ {{#each entryFromIntegration.data as | data |}}
+
+
+ {{ data.inventory_name }} |
+ {{ data.inventory_stock_entry_quantity }} ({{ data.inventory_unit }}) |
+
+
+
+ {{#if ../showDetails}}
+
+ {{#each data.inventory_stock_entry_data as | item |}}
+
+ {{ document_reference }} |
+ {{ description }} |
+ |
+ {{date date }} |
+ {{ quantity }} ({{ unit_text }}) |
+
+ {{/each}}
+
+ {{/if}}
+
+ {{/each}}
+
+
+ {{#if entryFromIntegration.isEmpty}}
+ {{translate 'STOCK.NO_DATA'}} |
+ {{/if}}
+
+ {{/if}}
+
+
+
+
+ {{#if includeDonationEntry}}
+
{{translate 'STOCK.RECEIPT.ENTRY_DONATION'}}
+
+
+ {{#each entryFromDonation.data as | data |}}
+
+
+ {{ data.inventory_name }} |
+ {{ data.inventory_stock_entry_quantity }} ({{ data.inventory_unit }}) |
+
+
+
+ {{#if ../showDetails}}
+
+ {{#each data.inventory_stock_entry_data as | item |}}
+
+ {{ document_reference }} |
+ {{ description }} |
+ |
+ {{date date }} |
+ {{ quantity }} ({{ unit_text }}) |
+
+ {{/each}}
+
+ {{/if}}
+
+ {{/each}}
+
+
+ {{#if entryFromDonation.isEmpty}}
+ {{translate 'STOCK.NO_DATA'}} |
+ {{/if}}
+
+ {{/if}}
+
+
+ {{#if includeTransferEntry}}
+
{{translate 'STOCK.RECEIPT.ENTRY_DEPOT'}}
+
+
+ {{#each entryFromTransfer.data as | data |}}
+
+
+ {{ data.inventory_name }} |
+ {{ data.inventory_stock_entry_quantity }} ({{ data.inventory_unit }}) |
+
+
+
+ {{#if ../showDetails}}
+
+ {{#each data.inventory_stock_entry_data as | item |}}
+
+ {{ document_reference }} |
+ {{ depot_name }} |
+ |
+ {{date date }} |
+ {{ quantity }} ({{ unit_text }}) |
+
+ {{/each}}
+
+ {{/if}}
+
+ {{/each}}
+
+
+ {{#if entryFromTransfer.isEmpty}}
+ {{translate 'STOCK.NO_DATA'}} |
+ {{/if}}
+
+ {{/if}}
+
+
+
+
+ {{#if includeLossEntry}}
+
{{translate 'STOCK.RECEIPT.ENTRY_LOSS'}}
+
+
+ {{#each entryToLoss.data as | data |}}
+
+
+ {{ data.inventory_name }} |
+ {{ data.inventory_stock_entry_quantity }} ({{ data.inventory_unit }}) |
+
+
+
+ {{#if ../showDetails}}
+
+ {{#each data.inventory_stock_entry_data as | item |}}
+
+ {{ document_reference }} |
+ {{ description }} |
+ |
+ {{date date }} |
+ {{ quantity }} ({{ unit_text }}) |
+
+ {{/each}}
+
+ {{/if}}
+
+ {{/each}}
+
+
+ {{#if entryToLoss.isEmpty}}
+ {{translate 'STOCK.NO_DATA'}} |
+ {{/if}}
+
+ {{/if}}
+
+
+
+
+
diff --git a/server/controllers/stock/reports/stock_inventory.report.handlebars b/server/controllers/stock/reports/stock_inventory.report.handlebars
index 5c9f263bd9..e9a4a42d56 100644
--- a/server/controllers/stock/reports/stock_inventory.report.handlebars
+++ b/server/controllers/stock/reports/stock_inventory.report.handlebars
@@ -60,17 +60,17 @@
{{!-- entry --}}
{{#if entry.quantity}}{{entry.quantity}}{{/if}} |
{{#if entry.unit_cost}}{{precision entry.unit_cost 4}}{{/if}} |
- {{#if entry.value}}{{currency entry.value ../../metadata.enterprise.currency_id}}{{/if}} |
+ {{#if entry.value}}{{currency entry.value ../metadata.enterprise.currency_id}}{{/if}} |
{{!-- exit --}}
{{#if exit.quantity}}{{exit.quantity}}{{/if}} |
{{#if exit.unit_cost}}{{precision exit.unit_cost 4}}{{/if}} |
- {{#if exit.value}}{{currency exit.value ../../metadata.enterprise.currency_id}}{{/if}} |
+ {{#if exit.value}}{{currency exit.value ../metadata.enterprise.currency_id}}{{/if}} |
{{!-- stock --}}
{{stock.quantity}} |
{{precision stock.unit_cost 4}} |
- {{currency stock.value ../../metadata.enterprise.currency_id}} |
+ {{currency stock.value ../metadata.enterprise.currency_id}} |
{{/each}}
@@ -82,7 +82,7 @@
{{ totals.exit}} | | |
{{ result.stock.quantity}} |
{{precision result.stock.unit_cost 4}} |
- {{currency result.stock.value ../../metadata.enterprise.currency_id}} |
+ {{currency result.stock.value metadata.enterprise.currency_id}} |
diff --git a/server/models/bhima.sql b/server/models/bhima.sql
index f8031ccfd1..f900cbb7d6 100644
--- a/server/models/bhima.sql
+++ b/server/models/bhima.sql
@@ -124,7 +124,8 @@ INSERT INTO unit VALUES
(236, 'Human Resources dashboard', 'TREE.DASHBOARDS.HUMAN_RESOURCES', 'Tableau de bord du Personnel', 233, '/modules/dashboards/staff/', '/dashboards/staff'),
(237, 'Finances dashboard', 'TREE.DASHBOARDS.FINANCES', 'Tableau de bord des finances', 233, '/modules/dashboards/finances/', '/dashboards/finances'),
(238, 'Indicators report', 'TREE.INDICATORS_REPORT', 'Rapport sur les indicateurs', 144,'/modules/reports/indicatorsReport', '/reports/indicatorsReport'),
- (239, 'Visits Report', 'TREE.VISITS_REPORT', 'Visits registry', 144, '/modules/reports/visit_report', '/reports/visit_report');
+ (239, 'Visits Report', 'TREE.VISITS_REPORT', 'Visits registry', 144, '/modules/reports/visit_report', '/reports/visit_report'),
+ (240, '[Stock] Stock Entry Report','TREE.STOCK_ENTRY_REPORT','Stock Entry Report', 144,'/modules/reports/generated/stock_entry','/reports/stock_entry');
-- Reserved system account type
INSERT INTO `account_category` VALUES
@@ -174,7 +175,8 @@ INSERT INTO `report` (`id`, `report_key`, `title_key`) VALUES
(29, 'breakEven', 'TREE.BREAK_EVEN_REPORT'),
(30, 'breakEvenFeeCenter', 'TREE.BREAK_EVEN_FEE_CENTER_REPORT'),
(31, 'indicatorsReport', 'TREE.INDICATORS_REPORT'),
- (32, 'visit_report', 'PATIENT_RECORDS.REPORT.VISITS');
+ (32, 'visit_report', 'PATIENT_RECORDS.REPORT.VISITS'),
+ (33, 'stock_entry', 'REPORT.STOCK.ENTRY_REPORT');
-- Supported Languages
INSERT INTO `language` VALUES
diff --git a/server/models/migrations/v1.1.0-v1.1.1/migrate.sql b/server/models/migrations/v1.1.0-v1.1.1/migrate.sql
index 7b2c637fab..a1ff80202f 100644
--- a/server/models/migrations/v1.1.0-v1.1.1/migrate.sql
+++ b/server/models/migrations/v1.1.0-v1.1.1/migrate.sql
@@ -134,9 +134,6 @@ BEGIN
END $$
DELIMITER ;
-DELETE FROM role_unit WHERE unit_id = 171;
-DELETE FROM unit WHERE id=171;
-
/*
@author: mbayopanda
@description: patient visits report
@@ -146,3 +143,13 @@ INSERT INTO unit VALUES
INSERT INTO `report` (`id`, `report_key`, `title_key`) VALUES
(32, 'visit_report', 'PATIENT_RECORDS.REPORT.VISITS');
+/*
+ @author: mbayopanda
+ @date: 2019-05-13
+ @description: stock entries report
+*/
+INSERT INTO unit VALUES
+ (240, '[Stock] Stock Entry Report','TREE.STOCK_ENTRY_REPORT','Stock Entry Report', 144,'/modules/reports/generated/stock_entry','/reports/stock_entry');
+
+INSERT INTO `report` (`id`, `report_key`, `title_key`) VALUES
+ (33, 'stock_entry', 'REPORT.STOCK.ENTRY_REPORT');