Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix stock performance issues #5143

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<th translate>FORM.LABELS.LOT</th>
</tr>
<tr ng-repeat="inventory in $ctrl.expiredInventories | limitTo : 5">
<td>{{inventory.text}} (<u translate-attr="{'title' : inventory.expiration_date_raw}">{{inventory.expiration_date}}</u>)</td>
<td>{{inventory.text}} (<u translate-attr="{'title' : inventory.expiration_date_raw}">{{inventory.expiration_date_parsed}}</u>)</td>
<td class="lot-width">{{inventory.label}}</td>
</tr>

Expand Down
2 changes: 1 addition & 1 deletion client/src/js/components/bhStockExpired/bhStockExpired.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ function bhStockExpiredController(Stock, moment, Notify, Depot, $filter) {
.then(inventories => {
inventories.forEach(inventory => {
inventory.expiration_date_raw = $date(inventory.expiration_date);
inventory.expiration_date = moment(inventory.expiration_date).fromNow();
inventory.expiration_date_parsed = moment(inventory.expiration_date).fromNow();
});

$ctrl.expiredInventories = inventories;
Expand Down
12 changes: 6 additions & 6 deletions client/src/js/components/bhStockSoldOut/bhStockSoldOut.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,27 @@

<table
class="table table-condensed table-bordered"
ng-show="$ctrl.soldOutInventories.length > 0">
ng-show="$ctrl.stockOutInventories.length > 0">
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better variable name!

<thead>
<tr>
<th>
<span class="text-danger"
translate-values="{ total : $ctrl.soldOutInventories.length }"
translate-values="{ total : $ctrl.stockOutInventories.length }"
translate="{{ 'STOCK.STOCK_OUT_WARNING' }}">
</span>
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat = "inventory in $ctrl.soldOutInventories | limitTo : 5">
<td>{{inventory.text}} (<u translate-attr="{ 'title' : inventory.stock_out_date_raw }">{{inventory.stock_out_date}}</u>)</td>
<tr ng-repeat = "inventory in $ctrl.stockOutInventories | limitTo : 5">
<td>{{inventory.text}} (<u translate-attr="{ 'title' : inventory.stock_out_date_raw }">{{inventory.stock_out_date_parsed}}</u>)</td>
</tr>

<tr>
<td>
<span class="text-danger"
ng-show="($ctrl.soldOutInventories.length - 5) > 0"
translate-values="{ left : ($ctrl.soldOutInventories.length - 5)}"
ng-show="($ctrl.stockOutInventories.length - 5) > 0"
translate-values="{ left : ($ctrl.stockOutInventories.length - 5)}"
translate="{{ 'STOCK.AND_MORE' }}">
</span>

Expand Down
7 changes: 4 additions & 3 deletions client/src/js/components/bhStockSoldOut/bhStockSoldOut.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ bhStockSoldOutController.$inject = ['StockService', 'moment', 'NotifyService', '
function bhStockSoldOutController(Stock, moment, Notify, $filter) {
const $ctrl = this;
$ctrl.loading = false;
$ctrl.soldOutInventories = [];
$ctrl.stockOutInventories = [];

const $date = $filter('date');

Expand All @@ -34,6 +34,7 @@ function bhStockSoldOutController(Stock, moment, Notify, $filter) {
*/
function fetchStockOuts() {
if (!$ctrl.depotUuid) return;

const dateTo = $ctrl.date || new Date();
$ctrl.loading = true;

Expand All @@ -45,10 +46,10 @@ function bhStockSoldOutController(Stock, moment, Notify, $filter) {
.then(inventories => {
inventories.forEach(inventory => {
inventory.stock_out_date_raw = $date(inventory.stock_out_date);
inventory.stock_out_date = moment(inventory.stock_out_date).fromNow();
inventory.stock_out_date_parsed = moment(inventory.stock_out_date).fromNow();
});

$ctrl.soldOutInventories = inventories;
$ctrl.stockOutInventories = inventories;
})
.catch(Notify.handleError)
.finally(() => {
Expand Down
26 changes: 24 additions & 2 deletions client/src/js/services/StockService.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ angular.module('bhima.services')
.service('StockService', StockService);

StockService.$inject = [
'PrototypeApiService', 'StockFilterer',
'PrototypeApiService', 'StockFilterer', 'HttpCacheService',
];

function StockService(Api, StockFilterer) {
function StockService(Api, StockFilterer, HttpCache) {
// API for stock lots
const stocks = new Api('/stock/lots');

Expand All @@ -23,6 +23,28 @@ function StockService(Api, StockFilterer) {
// API for stock inventory in depots
const inventories = new Api('/stock/inventories/depots');

// the stock inventories route gets hit a lot. Cache the results on the client.
inventories.read = cacheInventoriesRead;

const callback = (uuid, options) => Api.read.call(inventories, uuid, options);
const fetcher = HttpCache(callback, 5000);

/**
* The read() method loads data from the api endpoint. If an id is provided,
* the $http promise is resolved with a single JSON object, otherwise an array
* of objects should be expected.
*
* @param {String} uuid - the uuid of the inventory to fetch (optional).
* @param {Object} options - options to be passed as query strings (optional).
* @param {Boolean} cacheBust - ignore the cache and send the HTTP request directly
* to the server.
* @return {Promise} promise - resolves to either a JSON (if id provided) or
* an array of JSONs.
*/
function cacheInventoriesRead(uuid, options, cacheBust = false) {
return fetcher(uuid, options, cacheBust);
}

// API for stock inventory adjustment
const inventoryAdjustment = new Api('/stock/inventory_adjustment');

Expand Down
4 changes: 3 additions & 1 deletion client/src/modules/accounts/accounts.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ AccountService.$inject = [
];

/**
* Account Service
* @class AccountService
* @extends PrototypeApiService
*
* @description
* A service wrapper for the /accounts HTTP endpoint.
*/
function AccountService(Api, bhConstants, HttpCache) {
Expand Down
30 changes: 25 additions & 5 deletions client/src/modules/depots/depots.service.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
angular.module('bhima.services')
.service('DepotService', DepotService);

DepotService.$inject = ['PrototypeApiService', '$uibModal'];
DepotService.$inject = ['PrototypeApiService', '$uibModal', 'HttpCacheService'];

/**
* @class DepotService
Expand All @@ -10,10 +10,32 @@ DepotService.$inject = ['PrototypeApiService', '$uibModal'];
* @description
* Encapsulates common requests to the /depots/ URL.
*/
function DepotService(Api, Modal) {
function DepotService(Api, Modal, HttpCache) {
const baseUrl = '/depots/';
const service = new Api(baseUrl);

// debounce the read() call for depots
service.read = read;

const callback = (id, options) => Api.read.call(service, id, options);
const fetcher = HttpCache(callback, 250);

/**
* The read() method loads data from the api endpoint. If an id is provided,
* the $http promise is resolved with a single JSON object, otherwise an array
* of objects should be expected.
*
* @param {String} uuid - the uuid of the depot to fetch (optional).
* @param {Object} options - options to be passed as query strings (optional).
* @param {Boolean} cacheBust - ignore the cache and send the HTTP request directly
* to the server.
* @return {Promise} promise - resolves to either a JSON (if id provided) or
* an array of JSONs.
*/
function read(uuid, options, cacheBust = false) {
return fetcher(uuid, options, cacheBust);
}

/**
* @method openSelectionModal
*
Expand All @@ -29,9 +51,7 @@ function DepotService(Api, Modal) {
return Modal.open({
controller : 'SelectDepotModalController as $ctrl',
templateUrl : 'modules/stock/depot-selection.modal.html',
resolve : {
depot : () => depot,
},
resolve : { depot : () => depot },
}).result;
};

Expand Down
1 change: 0 additions & 1 deletion client/src/modules/stock/lots/registry.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,6 @@ function LotsRegistryService(uiGridConstants, Session) {
delete lot.expiration_date;
delete lot.lifetime;
delete lot.S_LOT_LIFETIME;
delete lot.S_RP;
}
};

Expand Down
5 changes: 4 additions & 1 deletion server/controllers/inventory/depots/extra.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ router.get('/inventories/:inventoryUuid/lots', getInventoryLots);
async function getInventory(req, res, next) {
try {
const monthAvgConsumption = req.session.stock_settings.month_average_consumption;
const averageConsumptionAlgo = req.session.stock_settings.average_consumption_algo;
const inventory = await core.getInventoryQuantityAndConsumption(
{ depot_uuid : req.params.uuid },
monthAvgConsumption,
averageConsumptionAlgo,
);

res.status(200).json(inventory);
Expand Down Expand Up @@ -97,7 +99,8 @@ async function getInventoryAverageMonthlyConsumption(req, res, next) {

async function getInventoryLots(req, res, next) {
try {
const inventory = await core.getLotsDepot(req.params.uuid, { inventory_uuid : req.params.inventoryUuid });
const options = { inventory_uuid : req.params.inventoryUuid, ...req.session.stock_settings };
const inventory = await core.getLotsDepot(req.params.uuid, options);
res.status(200).json(inventory);
} catch (err) {
next(err);
Expand Down
Loading