Skip to content

Commit

Permalink
Merge #6752
Browse files Browse the repository at this point in the history
6752: Add support for shipment containers r=jmcameron a=jmcameron

Adds support for breaking up a shipment into containers.  Each container could hold one or more shipment items. This PR also adds predefined container types, based on feedback from a current project.  This PR also adds documentation about containers to the shipments documentation.

**DESIGN GOALS**
- You should be able to create shipments like in the past with no containers.
- If you add a container, all shipment items not assigned to a container will be assigned to it
- If you have already created a container, all new shipment items will be added to the last container created.
- If you create a new shipment and add container(s) to it and then abandon it, no containers are created in the database

**NOTES**
- The shipment document has not been updated for containers yet.  That will be done in a future PR.
- Although the container types seem comprehensive, new types can be added by SQL updates.  If we decide that we need the ability to create new container types by users, we can implement that later.
- I have not tested this PR for migrations

**HOW TO USE CONTAINERS**
![container](https://user-images.githubusercontent.com/62145/180396208-31e73fb5-987d-4ff7-aff1-2bd29beaa532.png)
There are 4 new controls available in the shipments interface
1. [+ New Container] button -- Creates a new container (with a modal)
2. [Containers] button -- A drop-down menu of operations that can be performed on the containers for this shipment.  Note that this button will not be shown if there are no containers.  The operations available are **Edit**, **Assign items**, and **Delete**
![container-ops](https://user-images.githubusercontent.com/62145/180396556-35740b41-c1e1-4831-a85b-4749210b7ca8.png)
4. Container choice - This shows which container is selected for the shipment item.  (Not visible if there are no containers)
5. Multiple item select checkbox - You can assign any shipment items (lots) by using this checkbox and then using the "Assign Lots" option for the desired container in the container operations menu.

Closes #6740
Closes #6753

**TESTING SUGGESTIONS**
- Use bhima_test
- Download the attached SQL test file (and rename from .sql.txt to .sql) to use during testing to verify that the correct items are being created in the database during the testing operations
- Try creating a shipment without a container. It should work as it did before.
-Try various sequences of adding containers and items
  - Create a new shipment, add item(s), then create a container.  note that the the previous items are automatically added to the container.  Click [Submit] to save the shipment.
  - Try the attached `shiptest.sql` file to verify that the container is created as expected.
  - Create a new shipment, create a container, then add items.  the new items should be added to the last container created.  Save the new shipment
  - Try the attached `shiptest.sql` file to verify that the new shipment and container is created as expected.
  - Try creating a shipment with items and containers.  Then abort (press the [Clear] button at the bottom of the form.
  - Try the attached `shiptest.sql` file to verify that no new shipments or containers were created
  - Edit an existing shipment and try the various container operations.

[shiptest.sql.txt](https://github.com/IMA-WorldHealth/bhima/files/9166077/shiptest.sql.txt)



Co-authored-by: Jonathan Cameron <jmcameron@gmail.com>
  • Loading branch information
bors[bot] and jmcameron committed Jul 26, 2022
2 parents fc337e5 + 8f8d8e3 commit b4cdf42
Show file tree
Hide file tree
Showing 31 changed files with 1,179 additions and 132 deletions.
3 changes: 2 additions & 1 deletion client/src/i18n/en/form.json
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@
"LOOKUP_BY_ID": "By ID",
"LOOKUP_BY_NAME": "By Name",
"LOSS_ACCOUNT": "Loss Account",
"LOT": "Lot / Batch number",
"LOT": "Lot / Batch",
"MALE": "Male",
"MANUFACTURER_BRAND": "Manufacturer brand",
"MANUFACTURER_MODEL": "Manufacturer model",
Expand Down Expand Up @@ -930,6 +930,7 @@
"CHOICE_FILTER": "Choice Filter",
"CODE": "Enter code",
"CONDITION": "Condition",
"CONTAINER": "Container",
"COUNTRY": "Enter country",
"CREDITOR": "Enter creditor",
"CURRENCY": "Select currency",
Expand Down
28 changes: 28 additions & 0 deletions client/src/i18n/en/shipment.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,33 @@
{
"SHIPMENT" : {
"ASSIGN_LOTS": "Assign lots",
"ASSIGN_LOTS_TOOLTIP": "Assign the selected lots to this container",
"AUTHORIZED": "Authorized",
"ANTICIPATED_DELIVERY_DATE": "Anticipated delivery date",
"BARCODE": "Shipment Barcode",
"COMPLETE_SHIPMENT" : "Mark shipment as complete",
"CONTAINER": "Container",
"CONTAINERS": "Containers",
"CONTAINER_TYPE": "Container Type",
"CONTAINER_TYPES": {
"BALE": "bale",
"BOTTLE": "bottle",
"BOX": "box",
"BUNDLE": "bundle",
"CAN": "can",
"CARTON": "carton",
"CONTAINER": "container",
"CRATE": "crate",
"KIT": "kit",
"PACKAGE": "package",
"PACKET": "packet",
"PAIR": "pair",
"PALLET": "pallet",
"PIECES": "pieces",
"REAM": "ream",
"SACK": "sack",
"SET": "set"
},
"CREATE": "Create",
"CREATED": "Shipment successfully created",
"CREATED_BY": "Created by",
Expand All @@ -21,6 +45,7 @@
"DOES_SHIPMENT_EXIST_HELP": "Please provide the reference of a shipment that is ready to ship.",
"DUELY_RECEIVED_BY": "Duely received by",
"EDIT": "Edit",
"EDIT_CONTAINER": "Edit Container",
"EDIT_SHIPMENT": "Edit Shipment",
"ENTER_SHIPMENT_PROGRESS": "Please enter the shipment progress status. Include the current shipment location if it has changed.",
"ENTER_SHIPMENT_PROGRESS_HELP_TEXT": "Ex. RECEPTION - IMA GOMA WAREHOUSE, GOMA",
Expand Down Expand Up @@ -49,6 +74,7 @@
"MARK_READY_TO_SHIP_MESSAGE2": "(You will no longer be able to make changes to it.)",

"NAME_FUNCTION_SIGNATURE": "(name, function, signature)",
"NEW_CONTAINER": "New Container",
"NEW_LOCATION": "New Location",
"NEW_SHIPMENT": "New Shipment",
"NOT_DEFINED": "Not Defined",
Expand All @@ -63,6 +89,7 @@
"RECEIVER": "Receiver",
"REFERENCE": "Reference",
"REQUISITION": "Requisition",
"SELECT_CONTAINER_TYPE" : "Select Container Type",
"SHIPMENTS": "Shipments",
"SHIPMENT_CREATED": "Shipment created",
"SHIPMENT_DATE": "Expedition",
Expand All @@ -74,6 +101,7 @@
"STOCK_ENTRY_PARTIAL": "Partial stock entry for shipment performed",
"STOCK_EXITED_DONE": "Stock exit performed for the shipment",
"STOCK_REFERENCE": "Stock Reference",
"SUCCESFULLY_CREATED_CONTAINER": "Successfully created a new container",
"TITLE" : "Shipment",
"TOTAL_COST": "Total cost",
"TOTAL_QUANTITY": "Total quantity",
Expand Down
2 changes: 1 addition & 1 deletion client/src/i18n/en/table.json
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@
"LISTS": "Registered price list",
"LOADING": "Fetching data from the server.",
"LOCKED": "Locked",
"LOT": "Lot/ Batch number",
"LOT": "Lot / Batch",
"LONGITUDE": "Longitude",
"LATITUDE": "Latitude",
"MANUAL_DISTRIBUTION": "Manual distributions",
Expand Down
1 change: 1 addition & 0 deletions client/src/i18n/fr/form.json
Original file line number Diff line number Diff line change
Expand Up @@ -931,6 +931,7 @@
"CODE": "Entrer le code",
"COUNTRY": "Entrer le nom du pays",
"CONDITION": "Condition",
"CONTAINER": "Conteneur",
"CREDITOR": "Entrer un Créditeur",
"CURRENCY": "Sélectionner la monnaie",
"DEBTOR": "Entrer un Débiteur",
Expand Down
28 changes: 28 additions & 0 deletions client/src/i18n/fr/shipment.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,33 @@
{
"SHIPMENT" : {
"ASSIGN_LOTS": "Assigner des lots",
"ASSIGN_LOTS_TOOLTIP": "Assigner les lots sélectionnés à ce conteneur",
"AUTHORIZED": "Autorisé",
"ANTICIPATED_DELIVERY_DATE": "Date de livraison previsionnelle",
"BARCODE": "Code-barre de l'expédition",
"COMPLETE_SHIPMENT" : "Marquez l'expédition comme complète",
"CONTAINER": "Conteneur",
"CONTAINERS": "Conteneurs",
"CONTAINER_TYPE": "Type de conteneur",
"CONTAINER_TYPES" : {
"BALE": "ballot",
"BOTTLE": "flacon",
"BOX": "boite",
"BUNDLE": "botte",
"CAN": "bidon",
"CARTON": "carton",
"CONTAINER": "conteneur",
"CRATE": "caisse",
"KIT": "kit",
"PACKAGE": "colis",
"PACKET": "paquet",
"PAIR": "paire",
"PALLET": "pallet",
"PIECES": "pieces",
"REAM": "ramme",
"SACK": "sac",
"SET": "jeu"
},
"CREATE": "Créer",
"CREATED": "Expédition créee avec succès",
"CREATED_BY": "Crée par",
Expand All @@ -21,6 +45,7 @@
"DOES_SHIPMENT_EXIST_HELP": "Veuillez renseigner la référence de l'expédition prête",
"DUELY_RECEIVED_BY": "Pour réception conformé",
"EDIT": "Editer",
"EDIT_CONTAINER": "Modifier conteneur",
"EDIT_SHIPMENT": "Modifier expédition",
"ENTER_SHIPMENT_PROGRESS": "Veuillez entrer l'etat de progression de l'expédition avec sa localisation actuelle",
"ENTER_SHIPMENT_PROGRESS_HELP_TEXT": "Ex. RECEPTION - IMA GOMA WAREHOUSE, GOMA",
Expand Down Expand Up @@ -49,6 +74,7 @@
"MARK_READY_TO_SHIP_MESSAGE2": "(Vous ne pourrez plus y effectuer de modifications.)",

"NAME_FUNCTION_SIGNATURE": "(nom, fonction, signature)",
"NEW_CONTAINER": "Nouveau conteneur",
"NEW_LOCATION": "Nouvelle localisation",
"NEW_SHIPMENT": "Nouvelle expédition",
"NOT_DEFINED": "Non-défini",
Expand All @@ -63,6 +89,7 @@
"RECEIVER": "Récepteur",
"REFERENCE": "Reférence",
"REQUISITION": "Requisition",
"SELECT_CONTAINER_TYPE" : "Sélectionner le type de conteneur",
"SHIPMENTS": "Expéditions",
"SHIPMENT_CREATED": "Expédition créée",
"SHIPMENT_DATE": "Date de l'expédition",
Expand All @@ -74,6 +101,7 @@
"STOCK_ENTRY_PARTIAL": "Entrée en stock partielle pour l'expédition effectuée",
"STOCK_EXITED_DONE": "Sortie de stock effectuée pour l'expédition",
"STOCK_REFERENCE": "Stock Reférence",
"SUCCESFULLY_CREATED_CONTAINER": "Création d'un nouveau conteneur réussie avec succès",
"TITLE" : "Expedition",
"TOTAL_COST": "Côut total",
"TOTAL_QUANTITY": "Quantité totale",
Expand Down
5 changes: 5 additions & 0 deletions client/src/js/components/bhAddItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ angular.module('bhima.components')
bindings : {
callback : '&',
disable : '<?',
label : '<?',
},
});

Expand All @@ -21,6 +22,10 @@ function addItemController() {
// default value for incrementation
$ctrl.itemIncrement = 1;

if (!angular.isDefined($ctrl.label)) {
$ctrl.label = 'FORM.BUTTONS.ADD';
}

if (!angular.isDefined($ctrl.disable)) {
$ctrl.disable = false;
}
Expand Down
4 changes: 2 additions & 2 deletions client/src/js/services/grid/GridGrouping.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ function GridGroupingService(GridAggregators, uiGridGroupingConstants, Session,

/**
* contains the number of selected rows
* TODO : create a separate service to handle selection functionnality of the grid as grouping
* and selection are differents
* TODO : create a separate service to handle selection functionality of the grid as grouping
* and selection are different
*/
this.selectedRowCount = 0;
this.getSelectedGroups = getSelectedGroups.bind(this);
Expand Down
118 changes: 93 additions & 25 deletions client/src/modules/shipment/create-shipment.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@

<!-- date and note -->
<div class="row">

<div class="col-md-4">
<!-- shipment title -->
<bh-input-text
Expand Down Expand Up @@ -82,7 +83,7 @@

<!-- note -->
<div class="form-group"
ng-class="{ 'has-error' : ShipmentForm.$submitted && ShipmentForm.description.$invalid }">
ng-class="{ 'has-error' : ShipmentForm.$submitted && ShipmentForm.description.$invalid }">
<label class="control-label">
<span translate>FORM.LABELS.NOTES</span>
</label>
Expand All @@ -97,6 +98,10 @@
</div>
</div>

</div> <!-- end col-md-4 -->

<div class="col-md-4">

<div class="form-group" ng-class="{ 'has-error' : ShipmentForm.$submitted && ShipmentForm.receiver.$invalid }">
<label class="control-label" translate>SHIPMENT.RECEIVER</label>
<div>
Expand Down Expand Up @@ -126,12 +131,10 @@
</div>
</div>
</div>
</div>

<div class="col-md-4">
<!-- message panel to display actions the user needs to take -->
<div class="form-group" style="min-height: 12em;">
<label class="control-label" translate>STOCK.PENDING_ACTIONS</label>
<div class="form-group" style="min-height: 12em; border: 1px solid #D8D8D8; color: #888;">
<label class="control-label"><i translate>STOCK.PENDING_ACTIONS</i></label>

<p
style="padding-top:0"
Expand Down Expand Up @@ -159,28 +162,32 @@
</p>

</div>
</div>

<div ng-if="!CreateShipCtrl.existingShipmentUuid && CreateShipCtrl.alreadyAllocated.length" class="col-md-4">
<div class="form-group">
<div class="alert alert-warning" style="margin: 0;">
<span translate>SHIPMENT.EXISTING_ASSETS_IN_OTHER_SHIPMENT</span>
</div>
<div style="max-height: 200px; overflow-y: auto; margin: 0;">
<table class="table table-condensed table-bordered">
<tr>
<th translate>SHIPMENT.TITLE</th>
<th translate>ASSET.TITLE</th>
</tr>
<tr ng-repeat="item in CreateShipCtrl.alreadyAllocated track by item.uuid">
<td><a ng-click="CreateShipCtrl.getOverview(item.shipment_uuid)" href>{{ item.reference }}</a></td>
<td>{{ item.inventory_code + ' - ' + item.inventory_text + ' (' + item.lot_label + ')'}}</td>
</tr>
</table>
</div> <!-- end col-md-4 -->

<div class="col-md-4">
<div ng-if="!CreateShipCtrl.existingShipmentUuid && CreateShipCtrl.alreadyAllocated.length" >
<div class="form-group">
<div class="alert alert-warning" style="margin: 0;">
<span translate>SHIPMENT.EXISTING_ASSETS_IN_OTHER_SHIPMENT</span>
</div>
<div style="max-height: 200px; overflow-y: auto; margin: 0;">
<table class="table table-condensed table-bordered">
<tr>
<th translate>SHIPMENT.TITLE</th>
<th translate>ASSET.TITLE</th>
</tr>
<tr ng-repeat="item in CreateShipCtrl.alreadyAllocated track by item.uuid">
<td><a ng-click="CreateShipCtrl.getOverview(item.shipment_uuid)" href>{{ item.reference }}</a></td>
<td>{{ item.inventory_code + ' - ' + item.inventory_text + ' (' + item.lot_label + ')'}}</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>

</div> <!-- end row -->

<!-- not available messages -->
<div ng-if="CreateShipCtrl.inventoryNotAvailable.length" class="row">
Expand All @@ -207,9 +214,71 @@ <h4 translate>STOCK.PRODUCT_NOT_AVAILABLE</h4>
<div class="grid-toolbar-item">
<button class="btn btn-default" type="button" style="margin-left: 5px; vertical-align: middle;"
ng-click="CreateShipCtrl.getLotByBarcode()">
<span class="fa fa-plus-circle"></span> <span translate>BARCODE.SCAN</span> <span class="fa fa-barcode"></span>
<span class="fa fa-plus-circle"></span>
<span translate>BARCODE.SCAN_LOT_BARCODE</span>
<span class="fa fa-barcode"></span>
</button>
</div>

<div class="grid-toolbar-item" style="margin-left: 2em;">
<span class="input-group-btn">
<button
id="btn-new-container"
type="button"
class="btn btn-default"
ng-click="CreateShipCtrl.newContainer()">
<i class="fa fa-plus-circle"></i> <span translate>SHIPMENT.NEW_CONTAINER</span>
</button>
</span>
</div>

<div ng-if="CreateShipCtrl.containers.length" class="grid-toolbar-item" style="margin-left: 1em;">
<div uib-dropdown dropdown-append-to-body data-action="open-menu">
<a class="btn btn-default" uib-dropdown-toggle>
<span class="fa fa-bars"></span>
<span class="hidden-xs" translate>SHIPMENT.CONTAINERS</span>
<span class="caret"></span>
</a>

<ul uib-dropdown-menu role="menu" class="dropdown-menu-right" style="border: 3px double #CCC;">
<li>
<table class="table table-condensed" style="margin-bottom: 0.2em;">
<thead>
<tr>
<th translate>FORM.LABELS.LABEL</th>
<th translate>FORM.LABELS.TYPE</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="cont in CreateShipCtrl.containers">
<td>{{cont.label}}</td>
<td>{{cont.container_type}}</td>
<td>
<a href ng-click="CreateShipCtrl.editContainer(cont)">
<span class="fa fa-edit"></span> <span translate>FORM.LABELS.EDIT</span>
</a>
</td>
<td style="margin-right: 2em;">
<a href ng-click="CreateShipCtrl.assignShippingItems(cont)"
uib-tooltip="{{ 'SHIPMENT.ASSIGN_LOTS_TOOLTIP' | translate }}" tooltip-placement="bottom">
<i class="fa fa-check-square-o"></i> <span translate>SHIPMENT.ASSIGN_LOTS</span>
</a>
</td>
<td>
<a href ng-click="CreateShipCtrl.deleteContainer(cont)">
<span class="text-danger"><i class="fa fa-trash"></i> <span translate>FORM.BUTTONS.DELETE</span></span>
</a>
</td>
</tr>
</tbody>
</table>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
Expand Down Expand Up @@ -250,5 +319,4 @@ <h4 translate>STOCK.PRODUCT_NOT_AVAILABLE</h4>
</div>
</form>
</div>
<br />
</div>
Loading

0 comments on commit b4cdf42

Please sign in to comment.