From b5cac9505be08d155b79e9c87cfd6af12a8b32ab Mon Sep 17 00:00:00 2001 From: DominikNoga Date: Thu, 6 Jun 2024 16:55:36 +0200 Subject: [PATCH] Hadnled receive for facility and its wards --- .../admin-facility-view.module.js | 36 +++ .../facility-view.controller.js | 30 +- .../adjustment-creation.controller.js | 303 ++++++++++++------ .../adjustment-creation.controller.spec.js | 8 +- .../adjustment-creation.html | 40 ++- .../adjustment-creation.module.js | 3 +- .../adjustment-creation.routes.js | 117 +++++++ .../messages_en.json | 5 +- .../stock-adjustment-creation.scss | 2 +- src/stock-adjustment/messages_en.json | 13 + .../stock-adjustment.controller.js | 134 ++++++++ src/stock-adjustment/stock-adjustment.html | 29 ++ .../stock-adjustment.module.js | 32 ++ .../stock-adjustment.routes.js | 56 ++++ src/stock-adjustment/stock-adjustment.scss | 9 + .../stock-card-summary-repository.js | 69 ++++ .../orderable-group.service.js | 4 + ...full-stock-card-summary-repository-impl.js | 266 +++++++++++++++ src/stock-receive-creation/messages_en.json | 35 ++ .../receive-creation.module.js | 22 ++ .../receive-creation.routes.js | 129 ++++++++ 21 files changed, 1212 insertions(+), 130 deletions(-) create mode 100644 src/admin-facility-view/admin-facility-view.module.js create mode 100644 src/stock-adjustment-creation/adjustment-creation.routes.js create mode 100644 src/stock-adjustment/messages_en.json create mode 100644 src/stock-adjustment/stock-adjustment.controller.js create mode 100644 src/stock-adjustment/stock-adjustment.html create mode 100644 src/stock-adjustment/stock-adjustment.module.js create mode 100644 src/stock-adjustment/stock-adjustment.routes.js create mode 100644 src/stock-adjustment/stock-adjustment.scss create mode 100644 src/stock-card-summary/stock-card-summary-repository.js create mode 100644 src/stock-products/full-stock-card-summary-repository-impl.js create mode 100644 src/stock-receive-creation/messages_en.json create mode 100644 src/stock-receive-creation/receive-creation.module.js create mode 100644 src/stock-receive-creation/receive-creation.routes.js diff --git a/src/admin-facility-view/admin-facility-view.module.js b/src/admin-facility-view/admin-facility-view.module.js new file mode 100644 index 0000000..f09049f --- /dev/null +++ b/src/admin-facility-view/admin-facility-view.module.js @@ -0,0 +1,36 @@ +/* + * This program is part of the OpenLMIS logistics management information system platform software. + * Copyright © 2017 VillageReach + * + * This program is free software: you can redistribute it and/or modify it under the terms + * of the GNU Affero General Public License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + *   + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  + * See the GNU Affero General Public License for more details. You should have received a copy of + * the GNU Affero General Public License along with this program. If not, see + * http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  + */ + +(function() { + + 'use strict'; + + /** + * @module admin-facility-view + * + * @description + * Provides facility view screen for administrator. + */ + angular.module('admin-facility-view', [ + 'openlmis-rights', + 'openlmis-modal', + 'referencedata-facility', + 'referencedata-facility-type', + 'referencedata-geographic-zone', + 'referencedata-program', + 'referencedata-user', + 'ui.router' + ]); +})(); diff --git a/src/admin-facility-view/facility-view.controller.js b/src/admin-facility-view/facility-view.controller.js index 5c335b1..66ba426 100644 --- a/src/admin-facility-view/facility-view.controller.js +++ b/src/admin-facility-view/facility-view.controller.js @@ -32,13 +32,13 @@ '$q', '$state', 'facility', 'facilityTypes', 'geographicZones', 'facilityOperators', 'programs', 'FacilityRepository', 'loadingModalService', 'notificationService', 'tzPeriodService', 'messageService', 'confirmService', 'wards', 'wardService', - 'WARDS_CONSTANTS' + 'WARDS_CONSTANTS', 'currentUserService' ]; function controller($q, $state, facility, facilityTypes, geographicZones, facilityOperators, programs, FacilityRepository, loadingModalService, notificationService, tzPeriodService, messageService, confirmService, wards, wardService, - WARDS_CONSTANTS) { + WARDS_CONSTANTS, currentUserService) { var vm = this; @@ -174,6 +174,8 @@ */ vm.wardFacilityType = undefined; + vm.currentUser = undefined; + /** * @ngdoc method * @propertyOf admin-facility-view.controller:FacilityViewController @@ -199,6 +201,10 @@ }); vm.newWard = getInitialNewWardValue(); + currentUserService.getUserInfo().then(function(user) { + vm.currentUser = user; + }); + if (!vm.facilityWithPrograms.supportedPrograms) { vm.facilityWithPrograms.supportedPrograms = []; } @@ -243,7 +249,7 @@ * @methodOf admin-facility-view.controller:FacilityViewController * @name saveFacilityWithPrograms * - * @description + * @descriptioncurrentUserService * Saves facility with supported programs and redirects to facility list screen. */ function saveFacilityWithPrograms() { @@ -406,6 +412,24 @@ }); var addedWardsPromisses = vm.addedWards.map(function(ward) { + // assign user a role 9e2ee288-b77c-476e-9e15-a05d25c3dcda and a7993216-de2a-4031-b641-18621e3085cb + // for this facility + // var rolesIds = ['9e2ee288-b77c-476e-9e15-a05d25c3dcda', 'a7993216-de2a-4031-b641-18621e3085cb']; + + // var additionalRoleAssignments = vm.facility.supportedPrograms.map(function(program) { + // return [{ + // programId: program.id, + // warehouseId: '', + // }]; + // }) + + // $q.all(rolesIdsPromisses).then(function(responses) { + // console.log(responses); + // // var roleAssignments = currentUser.roleAssignments; + + // // console.log(roleAssignments); + // }); + return new FacilityRepository().create(ward); }); diff --git a/src/stock-adjustment-creation/adjustment-creation.controller.js b/src/stock-adjustment-creation/adjustment-creation.controller.js index a02981a..b992be9 100644 --- a/src/stock-adjustment-creation/adjustment-creation.controller.js +++ b/src/stock-adjustment-creation/adjustment-creation.controller.js @@ -41,7 +41,7 @@ // AO-805: Allow users with proper rights to edit product prices 'OrderableResource', 'permissionService', 'ADMINISTRATION_RIGHTS', 'authorizationService', // AO-805: Ends here - 'unitOfOrderableService' + 'unitOfOrderableService', 'wardService', 'orderableGroupsByWard' ]; function controller($scope, $state, $stateParams, $filter, confirmDiscardService, program, @@ -53,7 +53,8 @@ // ANGOLASUP-717: Create New Issue Report // AO-805: Allow users with proper rights to edit product prices accessTokenFactory, $window, stockmanagementUrlFactory, OrderableResource, permissionService, - ADMINISTRATION_RIGHTS, authorizationService, unitOfOrderableService) { + ADMINISTRATION_RIGHTS, authorizationService, unitOfOrderableService, wardService, + orderableGroupsByWard) { // ANGOLASUP-717: ends here // AO-805: Ends here var vm = this; @@ -162,6 +163,39 @@ */ vm.unitsOfOrderable = undefined; + /** + * @ngdoc property + * @propertyOf stock-adjustment-creation.controller:StockAdjustmentCreationController + * @name displayWardSelect + * @type {boolean} + * + * @description + * Holds information should the dialog used for ward selection be displayed + */ + vm.displayWardSelect = false; + + /** + * @ngdoc property + * @propertyOf stock-adjustment-creation.controller:StockAdjustmentCreationController + * @name homeFacilityWards + * @type {Object[]} + * + * @description + * Array of home facility wards + */ + vm.homeFacilityWards = []; + + /** + * @ngdoc property + * @propertyOf stock-adjustment-creation.controller:StockAdjustmentCreationController + * @name productDestination + * @type {Object} + * + * @description + * It is either ward or a whole home facility. Based on user input during lineItem adding + */ + vm.itemDestination = undefined; + // OAM-5: Lot code filter UI improvements. /** * @ngdoc method @@ -239,6 +273,10 @@ .findByLotInOrderableGroup(vm.selectedOrderableGroup, vm.selectedLot); } + if (!vm.itemDestination) { + vm.itemDestination = facility; + } + vm.newLot.expirationDateInvalid = undefined; vm.newLot.lotCodeInvalid = undefined; validateExpirationDate(); @@ -254,7 +292,8 @@ unitOfOrderableId: vm.newItemUnitId, unit: getUnitOfOrderableById(vm.newItemUnitId), price: getProductPrice(selectedItem), - totalPrice: 0 + totalPrice: 0, + destination: vm.itemDestination }, selectedItem, copyDefaultValue())); // AO-804: Ends here @@ -631,25 +670,9 @@ .value(); } - function confirmSubmit() { - loadingModalService.open(); - - var addedLineItems = angular.copy(vm.addedLineItems); - - generateKitConstituentLineItem(addedLineItems); - - var lotPromises = [], - errorLots = []; - var distinctLots = []; + function setLotPromisesAndErrorLots(distinctLots, lotPromises, errorLots) { var lotResource = new LotResource(); - addedLineItems.forEach(function(lineItem) { - lineItem.quantity = vm.getLineItemTotalQuantity(lineItem); - if (lineItem.lot && lineItem.$isNewItem && _.isUndefined(lineItem.lot.id) && - !listContainsTheSameLot(distinctLots, lineItem.lot)) { - distinctLots.push(lineItem.lot); - } - }); distinctLots.forEach(function(lot) { lotPromises.push(lotResource.create(lot) .then(function(createResponse) { @@ -677,36 +700,34 @@ })); }); + return lotPromises; + } + + function confirmSubmit() { + loadingModalService.open(); + var addedLineItems = angular.copy(vm.addedLineItems); + generateKitConstituentLineItem(addedLineItems); + var lotPromises = [], + errorLots = [], + distinctLots = []; + + addedLineItems.forEach(function(lineItem) { + lineItem.quantity = vm.getLineItemTotalQuantity(lineItem); + + if (lineItem.lot && lineItem.$isNewItem && _.isUndefined(lineItem.lot.id) && + !listContainsTheSameLot(distinctLots, lineItem.lot)) { + distinctLots.push(lineItem.lot); + } + }); + + setLotPromisesAndErrorLots(distinctLots, lotPromises, errorLots); + var productsWithPriceChanged = getProductsWithPriceChanged(addedLineItems); var lastProductWithPriceChanged = productsWithPriceChanged[productsWithPriceChanged.length - 1]; var priceChangesPromises = []; if (!lastProductWithPriceChanged) { - return stockAdjustmentCreationService.submitAdjustments(program.id, facility.id, - // AO-668: Use username as signature for Issue, Receive and Adjustment - addedLineItems, adjustmentType, user) - // AO-668: ends here - // ANGOLASUP-717: Create New Issue Report - .then(function(stockEventId) { - if (adjustmentType.state === ADJUSTMENT_TYPE.ISSUE.state) { - confirmService.confirm('adjustmentCreation.printModal.label', - 'stockPhysicalInventoryDraft.printModal.yes', - 'stockPhysicalInventoryDraft.printModal.no') - .then(function() { - $window.open(accessTokenFactory.addAccessToken(getPrintUrl(stockEventId)), - '_blank'); - }) - .finally(function() { - goToStockCardSummaries(); - }); - } else { - goToStockCardSummaries(); - } - // ANGOLASUP-717: ends here - }, function(errorResponse) { - loadingModalService.close(); - alertService.error(errorResponse.data.message); - }); + return createLotsAndSubmitAdjustments(addedLineItems, lotPromises, errorLots); } setProductPriceForProgram(lastProductWithPriceChanged, program); @@ -714,76 +735,133 @@ lastProductWithPriceChanged.price)); return $q.all(priceChangesPromises).then(function() { - return $q.all(lotPromises) - .then(function(responses) { - if (errorLots !== undefined && errorLots.length > 0) { - return $q.reject(); - } - responses.forEach(function(lot) { - addedLineItems.forEach(function(lineItem) { - if (lineItem.lot && lineItem.lot.lotCode === lot.lotCode - && lineItem.lot.tradeItemId === lot.tradeItemId) { - lineItem.lot = lot; - } - }); - return addedLineItems; - }); + return createLotsAndSubmitAdjustments(addedLineItems, lotPromises, errorLots); + }) + .catch(function(errorResponse) { + loadingModalService.close(); + $q.reject(); + alertService.error(errorResponse.data.message); + }); + } - stockAdjustmentCreationService.submitAdjustments(program.id, facility.id, - // AO-668: Use username as signature for Issue, Receive and Adjustment - addedLineItems, adjustmentType, user) - // AO-668: ends here - // ANGOLASUP-717: Create New Issue Report - .then(function(stockEventId) { - if (adjustmentType.state === ADJUSTMENT_TYPE.ISSUE.state) { - confirmService.confirm('adjustmentCreation.printModal.label', - 'stockPhysicalInventoryDraft.printModal.yes', - 'stockPhysicalInventoryDraft.printModal.no') - .then(function() { - $window.open(accessTokenFactory.addAccessToken(getPrintUrl(stockEventId)), - '_blank'); - }) - .finally(function() { - goToStockCardSummaries(); - }); - } else { - goToStockCardSummaries(); - } - // ANGOLASUP-717: ends here - }, function(errorResponse) { - loadingModalService.close(); - alertService.error(errorResponse.data.message); - }); - }) - .catch(function(errorResponse) { - loadingModalService.close(); - if (errorLots) { - var errorLotsReduced = errorLots.reduce(function(result, currentValue) { - if (currentValue.error in result) { - result[currentValue.error].push(currentValue.lotCode); - } else { - result[currentValue.error] = [currentValue.lotCode]; - } - return result; - }, {}); - for (var error in errorLotsReduced) { - alertService.error(error, errorLotsReduced[error].join(', ')); + function getLineItemsByDestinationMap(addedLineItems) { + var addedLineItemsMap = {}; + addedLineItems.forEach(function(lineItem) { + var destinationId = lineItem.destination.id; + if (!addedLineItemsMap[destinationId]) { + addedLineItemsMap[destinationId] = []; + } + addedLineItemsMap[destinationId].push(lineItem); + }); + return addedLineItemsMap; + } + + function createLotsAndSubmitAdjustments(addedLineItems, lotPromises, errorLots) { + return $q.all(lotPromises) + .then(function(responses) { + if (errorLots !== undefined && errorLots.length > 0) { + return $q.reject(); + } + responses.forEach(function(lot) { + addedLineItems.forEach(function(lineItem) { + if (lineItem.lot && lineItem.lot.lotCode === lot.lotCode + && lineItem.lot.tradeItemId === lot.tradeItemId) { + lineItem.lot = lot; } - vm.selectedOrderableGroup = undefined; - vm.selectedLot = undefined; - vm.lotChanged(); - return $q.reject(errorResponse.data.message); - } - alertService.error(errorResponse.data.message); + }); + return addedLineItems; }); - }) + + handleAdjustmentSubmission(addedLineItems); + }) .catch(function(errorResponse) { loadingModalService.close(); - $q.reject(); + if (errorLots) { + var errorLotsReduced = errorLots.reduce(function(result, currentValue) { + if (currentValue.error in result) { + result[currentValue.error].push(currentValue.lotCode); + } else { + result[currentValue.error] = [currentValue.lotCode]; + } + return result; + }, {}); + for (var error in errorLotsReduced) { + alertService.error(error, errorLotsReduced[error].join(', ')); + } + vm.selectedOrderableGroup = undefined; + vm.selectedLot = undefined; + vm.lotChanged(); + return $q.reject(errorResponse.data.message); + } alertService.error(errorResponse.data.message); }); } + function handleAdjustmentSubmission(addedLineItems) { + if (adjustmentType.state === ADJUSTMENT_TYPE.RECEIVE.state) { + return handleStockReceive(addedLineItems); + } + return submitAdjustment(addedLineItems); + } + + function handleStockReceive(addedLineItems) { + var lineItemsByDestinationMap = getLineItemsByDestinationMap(addedLineItems); + var submitAdjustmentPromises = []; + for (var key in lineItemsByDestinationMap) { + var lineItemsGroup = lineItemsByDestinationMap[key]; + submitAdjustmentPromises.push( + getSubmitAdjustmentPromise(lineItemsGroup, lineItemsGroup[0].destination) + ); + } + + return $q.all(submitAdjustmentPromises).then(function() { + goToStockCardSummaries(); + }); + } + + function getSubmitAdjustmentPromise(addedLineItems, facility) { + return stockAdjustmentCreationService.submitAdjustments(program.id, facility.id, + addedLineItems, adjustmentType, user); + } + + function submitAdjustment(addedLineItems) { + return getSubmitAdjustmentPromise(addedLineItems, facility) + // AO-668: ends here + // ANGOLASUP-717: Create New Issue Report + .then(function(stockEventId) { + if (adjustmentType.state === ADJUSTMENT_TYPE.ISSUE.state) { + confirmService.confirm('adjustmentCreation.printModal.label', + 'stockPhysicalInventoryDraft.printModal.yes', + 'stockPhysicalInventoryDraft.printModal.no') + .then(function() { + $window.open(accessTokenFactory.addAccessToken(getPrintUrl(stockEventId)), + '_blank'); + }) + .finally(function() { + goToStockCardSummaries(); + }); + } else { + goToStockCardSummaries(); + } + // ANGOLASUP-717: ends here + }, function(errorResponse) { + loadingModalService.close(); + alertService.error(errorResponse.data.message); + }); + } + + vm.itemDestinationChanged = function() { + if (vm.itemDestination) { + vm.orderableGroups = vm.orderableGroupsByWard.find(function(obj) { + return obj.wardId === vm.itemDestination.id; + }).orderableGroups; + return; + } + + vm.orderableGroups = orderableGroups; + vm.selectedOrderableGroup = undefined; + }; + // ANGOLASUP-717: Create New Issue Report function getPrintUrl(stockEventId) { var reportTemplateId = '79301ebf-1198-4a35-9d00-18c9fe450807'; @@ -907,6 +985,7 @@ vm.keyword = $stateParams.keyword; vm.orderableGroups = orderableGroups; + vm.orderableGroupsByWard = orderableGroupsByWard; vm.hasLot = false; vm.orderableGroups.forEach(function(group) { vm.hasLot = vm.hasLot || orderableGroupService.lotsOf(group, hasPermissionToAddNewLot).length > 0; @@ -921,6 +1000,18 @@ b[0].orderable.fullProductName); }); // OAM-5: ends here + + vm.displayWardSelect = adjustmentType.state === ADJUSTMENT_TYPE.RECEIVE.state; + if (vm.displayWardSelect) { + wardService.getWardsByFacility({ + zoneId: vm.facility.geographicZone.id + }).then(function(response) { + vm.homeFacilityWards = response.content.filter(function(responseFacility) { + return responseFacility.id !== vm.facility.id; + }); + }); + } + vm.showVVMStatusColumn = orderableGroupService.areOrderablesUseVvm(vm.orderableGroups); vm.hasPermissionToAddNewLot = hasPermissionToAddNewLot; vm.canAddNewLot = false; diff --git a/src/stock-adjustment-creation/adjustment-creation.controller.spec.js b/src/stock-adjustment-creation/adjustment-creation.controller.spec.js index 1528b4b..7df6177 100644 --- a/src/stock-adjustment-creation/adjustment-creation.controller.spec.js +++ b/src/stock-adjustment-creation/adjustment-creation.controller.spec.js @@ -18,7 +18,7 @@ describe('StockAdjustmentCreationController', function() { var vm, q, rootScope, state, stateParams, facility, program, confirmService, VVM_STATUS, messageService, scope, stockAdjustmentCreationService, reasons, $controller, ADJUSTMENT_TYPE, ProgramDataBuilder, FacilityDataBuilder, ReasonDataBuilder, OrderableGroupDataBuilder, OrderableDataBuilder, alertService, notificationService, - orderableGroups, LotDataBuilder, UNPACK_REASONS, LotResource, timeout; + orderableGroups, LotDataBuilder, UNPACK_REASONS, LotResource, timeout, orderableGroupsByWard; beforeEach(function() { @@ -53,6 +53,11 @@ describe('StockAdjustmentCreationController', function() { LotDataBuilder = $injector.get('LotDataBuilder'); UNPACK_REASONS = $injector.get('UNPACK_REASONS'); LotResource = $injector.get('LotResource'); + orderableGroupsByWard = $injector.get('orderableGroupsByWard'); + + console.log(orderableGroupsByWard); + + this.orderableGroupsByWard = $injector.get('orderableGroupsByWard'); this.OrderableDataBuilder = $injector.get('OrderableDataBuilder'); this.OrderableChildrenDataBuilder = $injector.get('OrderableChildrenDataBuilder'); this.offlineService = $injector.get('offlineService'); @@ -73,6 +78,7 @@ describe('StockAdjustmentCreationController', function() { orderableGroups = [ new OrderableGroupDataBuilder().build() ]; + reasons = [new ReasonDataBuilder().build()]; this.kitConstituents = [ diff --git a/src/stock-adjustment-creation/adjustment-creation.html b/src/stock-adjustment-creation/adjustment-creation.html index b39f6e1..15bb1f3 100644 --- a/src/stock-adjustment-creation/adjustment-creation.html +++ b/src/stock-adjustment-creation/adjustment-creation.html @@ -14,37 +14,40 @@

+
+ + +
-
- + + ng-change="vm.expirationDateChanged()" + openlmis-invalid="{{vm.newLot.expirationDateInvalid | message}}" />