Skip to content

Commit

Permalink
SELV3-508: Add validation to check unaccounted quantity
Browse files Browse the repository at this point in the history
  • Loading branch information
nlaskowska committed Jun 23, 2022
1 parent d3fbee8 commit 3154430
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/stock-physical-inventory-draft/messages_en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"stockPhysicalInventoryDraft.unaccountedQuantityError": "Unnacounted quantity must be 0"
}
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,28 @@
return lineItem.quantityInvalid;
};

// SELV3-508: Add validation to check unaccounted quantity
/**
* @ngdoc method
* @methodOf stock-adjustment-creation.controller:StockAdjustmentCreationController
* @name validateUnaccountedQuantity
*
* @description
* Validate line item quantity and returns self.
*
* @param {Object} lineItem line item to be validated.
*/
vm.validateUnaccountedQuantity = function(lineItem) {
if (lineItem.unaccountedQuantity === 0) {
lineItem.unaccountedQuantityInvalid = false;
} else {
lineItem.unaccountedQuantityInvalid = messageService
.get('stockPhysicalInventoryDraft.unaccountedQuantityError');
}
return lineItem.unaccountedQuantityInvalid;
};
// SELV3-508: ends here

function isEmpty(value) {
return value === '' || value === undefined || value === null;
}
Expand All @@ -655,7 +677,7 @@
.each(function(item) {
if (!item.active) {
activeError = 'stockPhysicalInventoryDraft.submitInvalidActive';
} else if (vm.validateQuantity(item)) {
} else if (vm.validateQuantity(item) || vm.validateUnaccountedQuantity(item)) {
qtyError = 'stockPhysicalInventoryDraft.submitInvalid';
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,13 +322,24 @@ describe('PhysicalInventoryDraftController', function() {
it('should show modal for occurred date if no quantity missing', function() {
this.lineItem1.active = true;
this.lineItem3.active = true;
// SELV3-508: Add validation to check unaccounted quantity
this.lineItem1.quantity = 1234;
this.lineItem3.quantity = 123;
this.lineItem1.stockAdjustments = [{
quantity: 1234,
reason: {
reasonType: 'CREDIT'
}
}];
this.lineItem3.stockAdjustments = [{
quantity: 123,
reason: {
reasonType: 'CREDIT'
}
}];
this.lineItem1.unaccountedQuantity = 0;
this.lineItem3.unaccountedQuantity = 0;
// SELV3-508: ends here
var deferred = this.$q.defer();
deferred.resolve();
chooseDateModalService.show.andReturn(deferred.promise);
Expand Down Expand Up @@ -365,13 +376,24 @@ describe('PhysicalInventoryDraftController', function() {
beforeEach(function() {
this.lineItem1.active = true;
this.lineItem3.active = true;
// SELV3-508: Add validation to check unaccounted quantity
this.lineItem1.quantity = 1234;
this.lineItem3.quantity = 123;
this.lineItem1.stockAdjustments = [{
quantity: 1234,
reason: {
reasonType: 'CREDIT'
}
}];
this.lineItem3.stockAdjustments = [{
quantity: 123,
reason: {
reasonType: 'CREDIT'
}
}];
this.lineItem1.unaccountedQuantity = 0;
this.lineItem3.unaccountedQuantity = 0;
// SELV3-508: ends here
spyOn(this.$window, 'open').andCallThrough();
chooseDateModalService.show.andReturn(this.$q.when({}));
spyOn(this.accessTokenFactory, 'addAccessToken').andCallThrough();
Expand Down
120 changes: 120 additions & 0 deletions src/stock-physical-inventory-draft/physical-inventory-draft.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<h2>
{{'stockPhysicalInventoryDraft.title' | message: {'facilityCode': vm.facility.code, 'facilityName': vm.facility.name, 'program': vm.program.name} }}
</h2>

<section class="openlmis-table-container">
<form ng-submit="vm.search()" openlmis-table-filter>
<fieldset class="form-group">
<label for="searchFor">{{'stockPhysicalInventoryDraft.keyword' | message}}</label>
<input id="searchFor" type="text" ng-model="vm.keyword" maxlength="50"/>
<label for="includeInactive">
<input id="includeInactive"
type="checkbox"
name="includeInactive"
ng-true-value="'true'"
ng-false-value="'false'"
ng-model="vm.includeInactive"/>

{{'stockPhysicalInventoryDraft.includeInactiveItems' | message}}
</label>
<input type="submit" value="{{'stockPhysicalInventoryDraft.search' | message}}"/>
</fieldset>
</form>

<openlmis-progressbar class="physical-inventory-draft-progress"
value="vm.itemsWithQuantity.length" max="vm.displayLineItemsGroup.length"
title="{{'stockPhysicalInventoryDraft.numberOfProductsComplete' | message: {'num': vm.itemsWithQuantity.length, 'total': vm.displayLineItemsGroup.length} }}">
</openlmis-progressbar>

<button class="pull-right add" ng-click="vm.addProducts()">
{{'stockPhysicalInventoryDraft.addProduct' | message}}
</button>

<saving-indicator class="draft-indicator" object="vm.dataChanged"/>

<table>
<caption ng-if="!vm.displayLineItemsGroup.length && !vm.stateParams.keyword">
{{'stockPhysicalInventoryDraft.noLineItems' | message}}
</caption>
<caption ng-if="!vm.displayLineItemsGroup.length && vm.stateParams.keyword">
{{'stockPhysicalInventoryDraft.noSearchResults' | message}}
</caption>
<thead>
<tr>
<th>{{'stockPhysicalInventoryDraft.productCode' | message}}</th>
<th>{{'stockPhysicalInventoryDraft.product' | message}}</th>
<th>{{'stockPhysicalInventoryDraft.lotCode' | message}}</th>
<th>{{'stockPhysicalInventoryDraft.expiryDate' | message}}</th>
<th class="col-sticky sticky-right">{{'stockPhysicalInventoryDraft.soh' | message}}</th>
<th class="col-sticky sticky-right">{{'stockPhysicalInventoryDraft.currentStock' | message}}</th>
<th ng-if="vm.showVVMStatusColumn" class="col-sticky sticky-right">{{'stockPhysicalInventoryDraft.VVMStatus' | message}}</th>
<th class="col-sticky sticky-right">{{'stockPhysicalInventoryDraft.reasons' | message}}</th>
<th class="col-sticky sticky-right">{{'stockPhysicalInventoryDraft.unaccountedQuantity' | message}}</th>
<th ng-if="vm.showHideButtonColumn" >{{'stockPhysicalInventoryDraft.actions' | message}}</th>
</tr>
</thead>
<tbody ng-repeat="(category, groupedLineItems) in vm.groupedCategories" tbody-title="{{category}}">
<tr ng-if="lineItems.length > 1" ng-repeat-start="lineItems in groupedLineItems">
<td>{{lineItems[0].orderable.productCode}}</td>
<td>{{lineItems[0].orderable | productName}}</td>
<td></td>
<td></td>
<td align="right">{{vm.calculate(lineItems, 'stockOnHand')}}</td>
<td align="right">{{vm.calculate(lineItems, 'quantity')}}</td>
<td ng-if="vm.showVVMStatusColumn"></td>
<td align="right"></td>
<td align="right"></td>
<td align="right" ng-if="vm.showHideButtonColumn"></td>
</tr>
<tr ng-repeat="lineItem in lineItems | orderBy:'lot?lot.lotCode:\'\''" ng-repeat-end>
<td>{{lineItems.length > 1 ? '' : lineItem.orderable.productCode}}</td>
<td>{{lineItems.length > 1 ? '' : (lineItem.orderable | productName)}}</td>
<td ng-if="vm.canEditLot(lineItem)">
<button class="edit" ng-click="vm.editLot(lineItem)">
{{lineItem.displayLotMessage}}
</button>
</td>
<td ng-if="!vm.canEditLot(lineItem)">
{{lineItem.displayLotMessage}}
</td>
<td>{{lineItem.lot.expirationDate | openlmisDate}}</td>
<td align="right">{{lineItem.stockOnHand}}</td>
<td class="digit-cell" >
<input
class="form-control" ng-blur="vm.validateQuantity(lineItem)"
ng-change="vm.quantityChanged(lineItem)"
ng-model="lineItem.quantity"
openlmis-invalid="{{lineItem.quantityInvalid ? lineItem.quantityInvalid : ''}}"
positive-integer/>
</td>
<td ng-if="vm.showVVMStatusColumn" class="digit-cell">
<select ng-if="lineItem.orderable.extraData.useVVM == 'true'"
ng-model="lineItem.vvmStatus"
ng-options="status as vm.getStatusDisplay(status) for status in vm.vvmStatuses"
placeholder="{{'stockPhysicalInventoryDraft.selectStatus' | message}}"
ng-change="vm.cacheDraft()">
</select>
</td>
<td class="reasons-cell" >
<!-- SELV3-508: Add validation to check unaccounted quantity -->
<stock-reasons
ng-model="lineItem.stockAdjustments"
line-item="lineItem"
reasons="vm.reasons"
ng-change="vm.checkUnaccountedStockAdjustments(lineItem); vm.validateUnaccountedQuantity(lineItem)"
/>
<td align="right"
openlmis-invalid="{{lineItem.unaccountedQuantityInvalid | message}}">{{lineItem.unaccountedQuantity}}</td>
</td>
<!-- SELV3-508: ends here -->
<td ng-if="vm.showHideButtonColumn">
<button type="button" class="danger" ng-if="lineItem.stockOnHand === 0 && lineItem.active && !lineItem.$isNewItem" ng-disabled="offlineService.isOffline()"
ng-click="vm.hideLineItem(lineItem)">{{'stockPhysicalInventoryDraft.deactivate' | message}}</button>
</td>
</tr>
</tbody>
</table>
<openlmis-pagination list="vm.displayLineItemsGroup" paged-list="vm.pagedLineItems" on-page-change="vm.saveOnPageChange"></openlmis-pagination>
</section>

<ng-include src="'stock-physical-inventory-draft/physical-inventory-draft-toolbar.html'"></ng-include>

0 comments on commit 3154430

Please sign in to comment.