From 4225771952e075ea5f71b23a173f89af4144457f Mon Sep 17 00:00:00 2001
From: Aliaksei Chumakou <aliaksei_chumakou@epam.com>
Date: Thu, 14 May 2020 00:43:51 +0300
Subject: [PATCH] UIOR-562 fix callout exceptions, previous username (#861)

* UIOR-562 fix callout exceptions, previous username
---
 CHANGELOG.md                                  |  6 ++
 package.json                                  |  2 +-
 src/components/LayerCollection/LayerPO.js     | 81 ++++++++++---------
 src/components/LayerCollection/LayerPOLine.js | 43 +++++-----
 src/components/POLine/POLine.js               |  8 +-
 src/components/PurchaseOrder/PO.js            | 24 +++---
 .../Utils/order/showUpdateOrderError.js       | 32 ++++----
 src/components/Utils/orderResource.js         |  2 +
 src/settings/OrderTemplates/OrderTemplates.js | 14 ++--
 9 files changed, 122 insertions(+), 90 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b6c21e68a..5ec0f57a6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,12 @@
 
 ## (IN PROGRESS)
 
+## [2.0.5](https://github.com/folio-org/ui-orders/tree/v2.0.5) (2020-05-13)
+[Full Changelog](https://github.com/folio-org/ui-orders/compare/v2.0.4...v2.0.5)
+
+### Bug fixes
+* [UIOR-562](https://issues.folio.org/browse/UIOR-562) Created By shows last clicked User name
+
 ## [2.0.4](https://github.com/folio-org/ui-orders/tree/v2.0.4) (2020-04-24)
 [Full Changelog](https://github.com/folio-org/ui-orders/compare/v2.0.3...v2.0.4)
 
diff --git a/package.json b/package.json
index 83ce1921a..0d1c52919 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@folio/orders",
-  "version": "2.0.4",
+  "version": "2.0.5",
   "description": "Description for orders",
   "main": "src/index.js",
   "repository": "",
diff --git a/src/components/LayerCollection/LayerPO.js b/src/components/LayerCollection/LayerPO.js
index 04ee352c8..7e1dcf5ca 100644
--- a/src/components/LayerCollection/LayerPO.js
+++ b/src/components/LayerCollection/LayerPO.js
@@ -1,10 +1,10 @@
 import React, { Component } from 'react';
 import PropTypes from 'prop-types';
-import { get } from 'lodash';
 import SafeHTMLMessage from '@folio/react-intl-safe-html';
 import ReactRouterPropTypes from 'react-router-prop-types';
 import { getFormValues } from 'redux-form';
 
+import { LoadingPane } from '@folio/stripes/components';
 import {
   CalloutContext,
   stripesConnect,
@@ -40,7 +40,11 @@ import { UpdateOrderErrorModal } from '../PurchaseOrder/UpdateOrderErrorModal';
 class LayerPO extends Component {
   static contextType = CalloutContext;
   static manifest = Object.freeze({
-    order: ORDER,
+    order: {
+      ...ORDER,
+      accumulate: true,
+      fetch: false,
+    },
     addresses: ADDRESSES,
     users: {
       ...USERS,
@@ -74,33 +78,41 @@ class LayerPO extends Component {
     mutator: PropTypes.object.isRequired,
   };
 
-  constructor(props) {
-    super(props);
+  constructor(props, context) {
+    super(props, context);
     this.state = {
-      createdByName: '',
-      assignedToUser: '',
       updateOrderError: null,
+      patchedOrder: {},
     };
   }
 
   componentDidMount() {
-    this.setUserFields();
-  }
-
-  getOrder = () => this.props.resources?.order?.records[0];
-
-  setUserFields = () => {
-    const { mutator } = this.props;
-    const { assignedTo, metadata } = this.getOrder() || {};
-
-    if (metadata) {
-      getUserNameById(mutator.users, get(metadata, 'createdByUserId'))
-        .then(userName => this.setState({ createdByName: userName }));
-    }
-
-    if (assignedTo) {
-      getUserNameById(mutator.users, assignedTo)
-        .then(userName => this.setState({ assignedToUser: userName }));
+    const { match: { params: { id } }, mutator } = this.props;
+
+    if (id) {
+      this.props.mutator.order.GET()
+        .then(o => Promise.all([
+          o,
+          getUserNameById(mutator.users, o.metadata?.createdByUserId),
+          getUserNameById(mutator.users, o.assignedTo),
+        ]), () => {
+          setTimeout(() => this.context?.sendCallout({
+            message: `Unable to load the order ${id}`,
+            type: 'error',
+            timeout: 0,
+          }));
+
+          return Promise.reject();
+        })
+        .then(([o, createdByName, assignedToUser]) => {
+          this.setState({
+            patchedOrder: {
+              ...o,
+              createdByName,
+              assignedToUser,
+            },
+          });
+        });
     }
   }
 
@@ -138,9 +150,11 @@ class LayerPO extends Component {
 
     return saveFn(order, mutator.order)
       .then(({ id, poNumber }) => {
-        this.context.sendCallout({
-          message: <SafeHTMLMessage id="ui-orders.order.save.success" values={{ orderNumber: poNumber }} />,
-        });
+        if (this.context) {
+          this.context.sendCallout({
+            message: <SafeHTMLMessage id="ui-orders.order.save.success" values={{ orderNumber: poNumber }} />,
+          });
+        }
         setTimeout(() => history.push({
           pathname: `/orders/view/${id}`,
           search: location.search,
@@ -159,17 +173,10 @@ class LayerPO extends Component {
       stripes,
     } = this.props;
     const id = match.params.id;
-    const order = id
-      ? this.getOrder()
-      : {};
-
-    if (!order) return null;
-    const { updateOrderError, createdByName, assignedToUser } = this.state;
-    const patchedOrder = {
-      ...order,
-      createdByName,
-      assignedToUser,
-    };
+    const { updateOrderError, patchedOrder } = this.state;
+
+    if (id && patchedOrder.id !== id) return <LoadingPane dismissible defaultWidth="fill" onClose={this.goToOrders} />;
+
     const formValues = getFormValues(PO_FORM_NAME)(stripes.store.getState());
 
     return (
diff --git a/src/components/LayerCollection/LayerPOLine.js b/src/components/LayerCollection/LayerPOLine.js
index 4e05aef26..957358629 100644
--- a/src/components/LayerCollection/LayerPOLine.js
+++ b/src/components/LayerCollection/LayerPOLine.js
@@ -92,8 +92,8 @@ class LayerPOLine extends Component {
     query: {},
   });
 
-  constructor(props) {
-    super(props);
+  constructor(props, context) {
+    super(props, context);
 
     this.state = {
       isLinesLimitExceededModalOpened: false,
@@ -115,6 +115,8 @@ class LayerPOLine extends Component {
     });
   };
 
+  sendCallout = (args) => this.context?.sendCallout(args);
+
   handleErrorResponse = async (e, line) => {
     let response;
 
@@ -130,13 +132,13 @@ class LayerPOLine extends Component {
       } else {
         const messageCode = get(ERROR_CODES, response.errors[0].code, 'orderLineGenericError');
 
-        this.context.sendCallout({
+        this.sendCallout({
           message: <SafeHTMLMessage id={`ui-orders.errors.${messageCode}`} />,
           type: 'error',
         });
       }
     } else {
-      this.context.sendCallout({
+      this.sendCallout({
         message: <SafeHTMLMessage id="ui-orders.errors.orderLineGenericError" />,
         type: 'error',
       });
@@ -149,19 +151,24 @@ class LayerPOLine extends Component {
 
     delete newLine.template;
 
-    poLines.POST(newLine)
-      .then(() => this.openOrder(saveAndOpen))
+    return poLines.POST(newLine)
+      .then(
+        () => {
+          this.sendCallout({
+            message: <SafeHTMLMessage id="ui-orders.line.create.success" />,
+            type: 'success',
+          });
+
+          return this.openOrder(saveAndOpen);
+        },
+        e => this.handleErrorResponse(e, line),
+      )
       .then(() => {
-        this.context.sendCallout({
-          message: <SafeHTMLMessage id="ui-orders.line.create.success" />,
-          type: 'success',
-        });
-        history.push({
+        setTimeout(() => history.push({
           pathname: `/orders/view/${id}`,
           search: location.search,
-        });
-      })
-      .catch(e => this.handleErrorResponse(e, line));
+        }), e => this.handleErrorResponse(e, line));
+      });
   };
 
   getOrder = () => get(this.props, 'resources.order.records.0');
@@ -186,7 +193,7 @@ class LayerPOLine extends Component {
         layer: null,
       });
     } catch (e) {
-      this.context.sendCallout({
+      this.sendCallout({
         message: <FormattedMessage id="ui-orders.errors.noCreatedOrder" />,
         type: 'error',
       });
@@ -202,13 +209,13 @@ class LayerPOLine extends Component {
     return saveAndOpen
       ? updateOrderResource(order, mutator.order, { workflowStatus: WORKFLOW_STATUS.open })
         .then(() => {
-          this.context.sendCallout({
+          this.sendCallout({
             message: <SafeHTMLMessage id="ui-orders.order.open.success" values={{ orderNumber: order.poNumber }} />,
             type: 'success',
           });
         })
         .catch(() => {
-          this.context.sendCallout({
+          this.sendCallout({
             message: <SafeHTMLMessage id="ui-orders.errors.openOrder" values={{ orderNumber: order.poNumber }} />,
             type: 'error',
           });
@@ -225,7 +232,7 @@ class LayerPOLine extends Component {
     return mutator.poLines.PUT(line)
       .then(() => this.openOrder(saveAndOpen))
       .then(() => {
-        this.context.sendCallout({
+        this.sendCallout({
           message: <SafeHTMLMessage id="ui-orders.line.update.success" values={{ lineNumber: line.poLineNumber }} />,
           type: 'success',
         });
diff --git a/src/components/POLine/POLine.js b/src/components/POLine/POLine.js
index 6aa87421e..bebac9b69 100644
--- a/src/components/POLine/POLine.js
+++ b/src/components/POLine/POLine.js
@@ -96,6 +96,8 @@ class POLine extends Component {
     return lines.find(u => u.id === lineId);
   }
 
+  sendCallout = (args) => this.context?.sendCallout(args);
+
   deleteLine = () => {
     const { mutator, poURL } = this.props;
     const line = this.getLine();
@@ -103,14 +105,14 @@ class POLine extends Component {
 
     mutator.poLine.DELETE(line)
       .then(() => {
-        this.context.sendCallout({
+        this.sendCallout({
           message: <SafeHTMLMessage id="ui-orders.line.delete.success" values={{ lineNumber }} />,
           type: 'success',
         });
         mutator.query.update({ _path: poURL });
       })
       .catch(async errorResponse => {
-        this.context.sendCallout({
+        this.sendCallout({
           message: <SafeHTMLMessage id="ui-orders.errors.lineWasNotDeleted" />,
           type: 'error',
         });
@@ -125,7 +127,7 @@ class POLine extends Component {
         } catch (e) {}
 
         if (message) {
-          this.context.sendCallout({
+          this.sendCallout({
             message,
             timeout: 0,
             type: 'error',
diff --git a/src/components/PurchaseOrder/PO.js b/src/components/PurchaseOrder/PO.js
index d613bfca6..da6194068 100644
--- a/src/components/PurchaseOrder/PO.js
+++ b/src/components/PurchaseOrder/PO.js
@@ -79,8 +79,8 @@ class PO extends Component {
     resources: PropTypes.object.isRequired,
   };
 
-  constructor(props) {
-    super(props);
+  constructor(props, context) {
+    super(props, context);
     this.state = {
       sections: {
         purchaseOrder: true,
@@ -106,6 +106,8 @@ class PO extends Component {
     this.setState(prevState => ({ isCloneConfirmation: !prevState.isCloneConfirmation }));
   };
 
+  sendCallout = (args) => this.context?.sendCallout(args);
+
   deletePO = () => {
     const { mutator } = this.props;
     const order = this.getOrder();
@@ -114,7 +116,7 @@ class PO extends Component {
     this.unmountDeleteOrderConfirm();
     mutator.order.DELETE(order)
       .then(() => {
-        this.context.sendCallout({
+        this.sendCallout({
           message: <SafeHTMLMessage id="ui-orders.order.delete.success" values={{ orderNumber }} />,
           type: 'success',
         });
@@ -124,7 +126,7 @@ class PO extends Component {
         });
       })
       .catch(() => {
-        this.context.sendCallout({
+        this.sendCallout({
           message: <SafeHTMLMessage id="ui-orders.errors.orderWasNotDeleted" />,
           type: 'error',
         });
@@ -173,8 +175,8 @@ class PO extends Component {
     };
 
     updateOrderResource(order, mutator.order, closeOrderProps)
-      .then(() => this.context.sendCallout({ message: <SafeHTMLMessage id="ui-orders.closeOrder.success" /> }))
-      .catch(() => this.context.sendCallout({
+      .then(() => this.context?.sendCallout({ message: <SafeHTMLMessage id="ui-orders.closeOrder.success" /> }))
+      .catch(() => this.context?.sendCallout({
         message: <SafeHTMLMessage id="ui-orders.closeOrder.error" />,
         type: 'error',
       }))
@@ -188,7 +190,7 @@ class PO extends Component {
 
     updateOrderResource(order, mutator.order, { approved: true })
       .then(() => {
-        this.context.sendCallout({
+        this.sendCallout({
           message: <SafeHTMLMessage id="ui-orders.order.approved.success" values={{ orderNumber }} />,
         });
       })
@@ -206,7 +208,7 @@ class PO extends Component {
 
     try {
       await updateOrderResource(order, mutator.order, openOrderProps);
-      this.context.sendCallout({
+      this.sendCallout({
         message: <SafeHTMLMessage id="ui-orders.order.open.success" values={{ orderNumber: order.poNumber }} />,
         type: 'success',
       });
@@ -226,7 +228,7 @@ class PO extends Component {
 
     try {
       await updateOrderResource(order, mutator.order, openOrderProps);
-      this.context.sendCallout({
+      this.sendCallout({
         message: <SafeHTMLMessage id="ui-orders.order.reopen.success" values={{ orderNumber: order.poNumber }} />,
         type: 'success',
       });
@@ -243,7 +245,7 @@ class PO extends Component {
     try {
       const newOrder = await cloneOrder(order, mutator.order, order.compositePoLines);
 
-      this.context.sendCallout({
+      this.sendCallout({
         message: <SafeHTMLMessage id="ui-orders.order.clone.success" />,
         type: 'success',
       });
@@ -373,7 +375,7 @@ class PO extends Component {
     );
 
     if (hasError && !this.hasError) {
-      this.context.sendCallout({
+      this.sendCallout({
         message: <SafeHTMLMessage id="ui-orders.errors.orderNotLoaded" />,
         type: 'error',
       });
diff --git a/src/components/Utils/order/showUpdateOrderError.js b/src/components/Utils/order/showUpdateOrderError.js
index 5d64aaed3..1176b426c 100644
--- a/src/components/Utils/order/showUpdateOrderError.js
+++ b/src/components/Utils/order/showUpdateOrderError.js
@@ -10,16 +10,18 @@ const POL_NUMBER_KEY = 'poLineNumber';
 const showMessage = (callout, code, error, path) => {
   const title = get(error, 'errors.0.parameters.0.value', '');
 
-  callout.sendCallout({
-    type: 'error',
-    message: (
-      <FormattedMessage
-        id={`ui-orders.errors.${code}`}
-        values={{ value: <Link to={`/settings/inventory/${path}`}>{title}</Link> }}
-      />
-    ),
-    timeout: 0,
-  });
+  if (callout) {
+    callout.sendCallout({
+      type: 'error',
+      message: (
+        <FormattedMessage
+          id={`ui-orders.errors.${code}`}
+          values={{ value: <Link to={`/settings/inventory/${path}`}>{title}</Link> }}
+        />
+      ),
+      timeout: 0,
+    });
+  }
 };
 
 const showUpdateOrderError = async (response, callout, openModal, genericCode = 'orderGenericError1') => {
@@ -65,10 +67,12 @@ const showUpdateOrderError = async (response, callout, openModal, genericCode =
       break;
     }
     default: {
-      callout.sendCallout({
-        message: <FormattedMessage id={`ui-orders.errors.${code}`} />,
-        type: 'error',
-      });
+      if (callout) {
+        callout.sendCallout({
+          message: <FormattedMessage id={`ui-orders.errors.${code}`} />,
+          type: 'error',
+        });
+      }
     }
   }
 };
diff --git a/src/components/Utils/orderResource.js b/src/components/Utils/orderResource.js
index 20a177560..1c1eb8353 100644
--- a/src/components/Utils/orderResource.js
+++ b/src/components/Utils/orderResource.js
@@ -14,6 +14,8 @@ const saveOrder = (order, mutator) => {
     delete order.compositePoLines;
   }
 
+  if (!order.metadata?.createdByUserId) delete order.metadata; // fix sample data
+
   return method(order);
 };
 
diff --git a/src/settings/OrderTemplates/OrderTemplates.js b/src/settings/OrderTemplates/OrderTemplates.js
index 32d9f93ec..34ed976a2 100644
--- a/src/settings/OrderTemplates/OrderTemplates.js
+++ b/src/settings/OrderTemplates/OrderTemplates.js
@@ -33,8 +33,8 @@ class OrderTemplates extends Component {
     resources: PropTypes.object,
   };
 
-  constructor(props) {
-    super(props);
+  constructor(props, context) {
+    super(props, context);
 
     const { stripes } = props;
 
@@ -50,10 +50,12 @@ class OrderTemplates extends Component {
   }
 
   showSuccessDeleteMessage = () => {
-    this.context.sendCallout({
-      type: 'success',
-      message: <FormattedMessage id="ui-orders.settings.orderTemplates.remove.success" />,
-    });
+    if (this.context) {
+      this.context.sendCallout({
+        type: 'success',
+        message: <FormattedMessage id="ui-orders.settings.orderTemplates.remove.success" />,
+      });
+    }
   }
 
   render() {