Skip to content

Commit

Permalink
Enable editing lot expiration dates during stock entry
Browse files Browse the repository at this point in the history
  • Loading branch information
jmcameron committed Jun 28, 2021
1 parent e822348 commit da85363
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 31 deletions.
2 changes: 2 additions & 0 deletions client/src/i18n/en/stock.json
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,8 @@
"LOTS" : {
"REGISTRY" : "Lots Registry",
"MERGED_LOTS_AUTOMATICALLY": "Automatically merged {{numLots}} lots for {{numInventories}} articles of inventory",
"ENABLE_CORRECTING_LOT_EXPIRATION_DATES": "Enable correction of lot expiration dates",
"ENABLE_CORRECTING_LOT_EXPIRATION_DATES_DESCRIPTION": "Enable correction of the expiration dates for existing lots.",
"ENABLE_FAST_INSERT": "Enable fast lots insertions",
"ENABLE_FAST_INSERT_DESCRIPTION": "This option will automatically select the next blank row's serial/lot number in the entry table. If necessary, it adds a new row. Useful for quickly inserting with a barcode reader",
"EXCLUDE_EXHAUSTED_LOTS": "Exclude exhausted lots",
Expand Down
2 changes: 2 additions & 0 deletions client/src/i18n/fr/stock.json
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,8 @@
"LOTS" : {
"REGISTRY" : "Registre des lots",
"MERGED_LOTS_AUTOMATICALLY": "{{NumLots}} lots fusionnés automatiquement pour {{numInventories}} articles d'inventaire",
"ENABLE_CORRECTING_LOT_EXPIRATION_DATES": "Permettre la correction des dates d'expiration des lots",
"ENABLE_CORRECTING_LOT_EXPIRATION_DATES_DESCRIPTION": "Permettre la correction des dates d'expiration des lots existants.",
"ENABLE_FAST_INSERT": "Activer les insertions rapides",
"ENABLE_FAST_INSERT_DESCRIPTION": "Cette option selectionne automatiquement une nouvelle ligne de lot lorsque vous finissez d'introduire un libellé de lot ou numéro de serie. C'est très utile lorsque vous utilisez un lecteur de code barre",
"EXCLUDE_EXHAUSTED_LOTS": "Exclure les lots de stocks épuisés",
Expand Down
26 changes: 21 additions & 5 deletions client/src/modules/stock/entry/modals/lots.modal.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<form
name="FindForm"
bh-submit="$ctrl.submit(FindForm)"
ng-model-options="{ 'debounce' : { 'default' : 200, 'blur' : 0 }}"
novalidate>

Expand All @@ -17,7 +18,7 @@
<div class="col-xs-12">
<div>
<span class="text-bold" translate>STOCK.ENTRY_DATE</span> :
{{ $ctrl.entryDate | date:$ctrl.Constants.dates.format }}
{{ $ctrl.entryDate | date:$ctrl.bhConstants.dates.format }}
</div>
</div>
</div>
Expand Down Expand Up @@ -73,7 +74,22 @@
<p class="help-block" translate>LOTS.ENABLE_FAST_INSERT_DESCRIPTION</p>
</div>

<bh-add-item callback="$ctrl.form.addItem()" disable="true">
<div style="margin-bottom: 5px;" bh-has-permission="$ctrl.bhConstants.actions.EDIT_LOT">
<div class="checkbox">
<label>
<input
id="editExpirationDates"
type="checkbox"
ng-model="$ctrl.editExpirationDates"
ng-change="$ctrl.onExpDateEditable()"
ng-true-value="1"
ng-false-value="0">
<span translate>LOTS.ENABLE_CORRECTING_LOT_EXPIRATION_DATES</span>
</label>
<p class="help-block" translate>LOTS.ENABLE_CORRECTING_LOT_EXPIRATION_DATES_DESCRIPTION</p>
</div>

<bh-add-item callback="$ctrl.form.addItem()" disable="true">
</bh-add-item>
</div>

Expand Down Expand Up @@ -105,8 +121,8 @@
FORM.BUTTONS.CLOSE
</button>

<button type="submit" class="btn btn-primary" ng-click="$ctrl.submit(FindForm, $event)" data-method="submit" translate>
FORM.BUTTONS.SUBMIT
</button>
<bh-loading-button loading-state="FindForm.$loading">
<span translate>FORM.BUTTONS.SUBMIT</span>
</bh-loading-button>
</div>
</form>
80 changes: 55 additions & 25 deletions client/src/modules/stock/entry/modals/lots.modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ angular.module('bhima.controllers')
.controller('StockDefineLotsModalController', StockDefineLotsModalController);

StockDefineLotsModalController.$inject = [
'appcache', '$uibModalInstance', 'uiGridConstants', 'data', 'SessionService',
'CurrencyService', 'NotifyService', 'bhConstants', 'StockEntryModalForm',
'$translate', 'focus',
'appcache', '$uibModalInstance', 'uiGridConstants', 'data', 'LotService',
'SessionService', 'CurrencyService', 'NotifyService', 'StockEntryModalForm',
'bhConstants', '$translate', 'focus',
];

function StockDefineLotsModalController(
AppCache, Instance, uiGridConstants, Data, Session,
Currencies, Notify, bhConstants, EntryForm,
$translate, Focus,
AppCache, Instance, uiGridConstants, Data, Lots,
Session, Currencies, Notify, EntryForm,
bhConstants, $translate, Focus,
) {
const vm = this;

Expand All @@ -26,7 +26,7 @@ function StockDefineLotsModalController(
rows : Data.stockLine.lots,
});

vm.Constants = bhConstants;
vm.bhConstants = bhConstants;
vm.hasMissingLotIdentifier = false;
vm.hasInvalidLotExpiration = false;
vm.hasInvalidLotQuantity = false;
Expand All @@ -47,13 +47,16 @@ function StockDefineLotsModalController(
vm.onLotBlur = onLotBlur;
vm.onChanges = onChanges;
vm.onChangeQuantity = onChangeQuantity;
vm.onExpDateEditable = onExpDateEditable;
vm.onChangeUnitCost = onChangeUnitCost;
vm.onDateChange = onDateChange;

vm.onSelectLot = onSelectLot;

vm.isCostEditable = (vm.entryType !== 'transfer_reception');

vm.editExpirationDates = false;

const cols = [{
field : 'status',
width : 25,
Expand Down Expand Up @@ -141,6 +144,18 @@ function StockDefineLotsModalController(
.find(l => l.uuid === uuid);
}

/**
* @method getExistingLot
*
* @description
* If the lot given is a string, it is a label, so look it up by label.
* If the lot is not a string, it will contain the lots UUID, use it to look up the lot
* @param {lot} the 'lot' object from the lot selection popup modal form
*/
function getExistingLot(lot) {
return typeof lot === 'string' ? lookupLotByLabel(lot) : lookupLotByUuid(lot.uuid);
}

// Handle the extra validation for expired lot labels
function validateForm() {
vm.errors = vm.form.validate(vm.entryDate);
Expand All @@ -151,17 +166,9 @@ function StockDefineLotsModalController(
return;
}

// Note that the type of row.lot will differ depending on whether
// we are selecting an existing lot or creating a new one.
const existingLot = typeof row.lot === 'string'
? lookupLotByLabel(row.lot)
: lookupLotByUuid(row.lot.uuid);
const existingLot = getExistingLot(row.lot);

if (existingLot) {
// Disable changing the date for rows with lots already defined.
// (This does not prevent changing the quantity.)
row.disabled = true;
}
row.editExpDateDisabled = (existingLot && !vm.editExpirationDates);

// Check to make sure the lot has not expired
if (existingLot && existingLot.expired) {
Expand Down Expand Up @@ -250,6 +257,15 @@ function StockDefineLotsModalController(
onChanges();
}

function onExpDateEditable() {
vm.form.rows.forEach((row) => {
if (row.lot === null) {
return;
}
row.editExpDateDisabled = (getExistingLot(row.lot) && !vm.editExpirationDates);
});
}

function onChangeUnitCost() {
vm.form.setUnitCost(vm.stockLine.unit_cost);
onChanges();
Expand Down Expand Up @@ -280,7 +296,7 @@ function StockDefineLotsModalController(
function onSelectLot(entity, item) {
const lot = vm.stockLine.candidateLots.find(l => l.uuid === item.uuid);
entity.expiration_date = new Date(lot.expiration_date);
entity.disabled = true;
entity.editExpDateDisabled = !vm.editExpirationDates;
onChanges();
}

Expand All @@ -296,7 +312,7 @@ function StockDefineLotsModalController(
// on the quantity, since the "min" property is set on the input. So, we
// need to through a generic error here.
if (form.$invalid) {
return;
return 0;
}

// Handle differences in selecting vs creating lots
Expand All @@ -309,12 +325,26 @@ function StockDefineLotsModalController(
});

if (vm.errors.length === 0) {
saveSetting();
Instance.close({
lots : vm.form.rows,
unit_cost : vm.stockLine.unit_cost,
quantity : vm.form.total(),
});

// Maybe update some lot expiration dates
const promises = [];
if (vm.editExpirationDates) {
vm.form.rows.forEach((row) => {
const existingLot = getExistingLot(row.lot);
if (existingLot && (row.expiration_date !== existingLot.expiration_date)) {
promises.push(Lots.update(existingLot.uuid, { expiration_date : row.expiration_date }));
}
});
}
return Promise.all(promises)
.then(() => {
saveSetting();
Instance.close({
lots : vm.form.rows,
unit_cost : vm.stockLine.unit_cost,
quantity : vm.form.total(),
});
});
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<bh-date-picker
date="row.entity.expiration_date"
on-change="grid.appScope.onDateChange(date, row.entity)"
disabled="row.entity.disabled"
disabled="row.entity.editExpDateDisabled"
required="true">
</bh-date-picker>
</div>

0 comments on commit da85363

Please sign in to comment.