
# HG changeset patch
# User Guillermo Alvarez de Eulate <guillermo.alvarez@openbravo.com>
# Date 1507880077 -7200
# Node ID e25140ad03838d34a02a7e411d22f7e8510362f0
# Parent  6b5524e30c63f76405668b2107055c4f0040b671
Related to issue 36966: Adapt stock validation module to -support for attributes- project

- When the attributes sent by client side are not valid -> Show error in the frontend
- When an item is not present in m_storage_detail try to pick different locator to use it as overissue
- When a quoation is approved and transformed into a sales order, the stock for the specific attribute is checked. it was not working

diff -r 6b5524e30c63 -r e25140ad0383 src/org/openbravo/retail/stockvalidation/OrderFromQuotationStockChecker.java
--- a/src/org/openbravo/retail/stockvalidation/OrderFromQuotationStockChecker.java	Thu Oct 12 18:24:45 2017 +0200
+++ b/src/org/openbravo/retail/stockvalidation/OrderFromQuotationStockChecker.java	Fri Oct 13 09:34:37 2017 +0200
@@ -4,6 +4,7 @@
 
 import javax.servlet.ServletException;
 
+import org.apache.commons.lang.StringUtils;
 import org.codehaus.jettison.json.JSONArray;
 import org.codehaus.jettison.json.JSONException;
 import org.codehaus.jettison.json.JSONObject;
@@ -12,7 +13,9 @@
 import org.openbravo.base.exception.OBException;
 import org.openbravo.dal.core.OBContext;
 import org.openbravo.dal.service.OBDal;
+import org.openbravo.mobile.core.utils.OBMOBCUtils;
 import org.openbravo.retail.posterminal.JSONProcessSimple;
+import org.openbravo.retail.posterminal.utility.AttributesUtils;
 
 public class OrderFromQuotationStockChecker extends JSONProcessSimple {
   @Override
@@ -39,10 +42,18 @@
           String productId = "";
           String productIdentifier = "";
           String lineIndex = "";
+          String attributeValue = "";
+          String validatedAttrSetInstanceDescription = "";
           BigDecimal qtyToBuy;
           currentTicketLine = linesOfTicket.getJSONObject(i);
           qtyToBuy = new BigDecimal(currentTicketLine.getString("qty"));
           productId = currentTicketLine.getString("productid");
+          if (OBMOBCUtils.isJsonObjectPropertyStringPresentNotNullAndNotEmptyString(
+              currentTicketLine, "attributeValue")) {
+            attributeValue = currentTicketLine.getString("attributeValue");
+            validatedAttrSetInstanceDescription = AttributesUtils
+                .generateValidAttSetInstanceDescription(attributeValue, productId);
+          }
           productIdentifier = currentTicketLine.getString("productidentifier");
           lineIndex = currentTicketLine.getString("index");
           String hqlQuery = "select sum(ms.quantityOnHand) as qtyonhand "
@@ -50,11 +61,15 @@
               + "SELECT ow.warehouse.id " + "FROM OrganizationWarehouse as ow " + "WHERE "
               + "ow.organization.id = :orgId) and ms.product.id = :productId "
               + "and ms.quantityOnHand > 0 and ms.quantityOnHand > ms.reservedQty";
+          if (attributeValue != null && !attributeValue.isEmpty())
+            hqlQuery += " and ms.attributeSetValue.description = :attSetInstanceDesc";
 
           final Session session = OBDal.getInstance().getSession();
           final Query query = session.createQuery(hqlQuery);
           query.setString("orgId", orgId);
           query.setString("productId", productId);
+          if (attributeValue != null && !attributeValue.isEmpty())
+            query.setString("attSetInstanceDesc", validatedAttrSetInstanceDescription);
 
           if (query.uniqueResult() != null) {
             unitsFound = new BigDecimal(query.uniqueResult().toString());
@@ -66,9 +81,13 @@
             allowSell = true;
           } else {
             String hqlQueryStatus = "select ms.storageBin.id as overissueStoreBin "
-                + "from MaterialMgmtStorageDetail ms " + "where ms.storageBin.warehouse.id in ("
-                + "SELECT ow.warehouse.id " + "FROM OrganizationWarehouse as ow "
-                + "WHERE " + "ow.organization.id = :orgId) " + "and ms.product.id = :productId "
+                + "from MaterialMgmtStorageDetail ms "
+                + "where ms.storageBin.warehouse.id in ("
+                + "SELECT ow.warehouse.id "
+                + "FROM OrganizationWarehouse as ow "
+                + "WHERE "
+                + "ow.organization.id = :orgId) "
+                + "and ms.product.id = :productId "
                 + "and ms.storageBin.inventoryStatus.overissue = 'Y' order by ms.storageBin.relativePriority";
             final Session sessionStatus = OBDal.getInstance().getSession();
             final Query queryStatus = sessionStatus.createQuery(hqlQueryStatus);
@@ -81,6 +100,27 @@
               overissueQty = qtyToBuy.subtract(unitsFound);
             } else {
               overissueStoreBin = "";
+              if (StringUtils.isEmpty(overissueStoreBin)) {
+                String hqlQueryAnyOverissueBin = "select loc.id as overissueStoreBin "
+                    + "from Locator loc " //
+                    + "where loc.warehouse.id in (" //
+                    + "  SELECT ow.warehouse.id " //
+                    + "  FROM OrganizationWarehouse as ow " //
+                    + "  WHERE ow.organization.id = :orgId" //
+                    + "  ) " //
+                    + "AND loc.inventoryStatus.overissue = 'Y' " //
+                    + "ORDER BY loc.relativePriority ASC";
+                final Query queryAnyOverissueBin = OBDal.getInstance().getSession()
+                    .createQuery(hqlQueryAnyOverissueBin);
+                queryAnyOverissueBin.setString("orgId", orgId);
+                queryAnyOverissueBin.setMaxResults(1);
+                if (queryAnyOverissueBin.uniqueResult() != null) {
+                  overissueStoreBin = (String) queryAnyOverissueBin.uniqueResult();
+                  overissueQty = BigDecimal.ZERO;
+                } else {
+                  overissueStoreBin = "";
+                }
+              }
             }
           }
 
diff -r 6b5524e30c63 -r e25140ad0383 src/org/openbravo/retail/stockvalidation/StockChecker.java
--- a/src/org/openbravo/retail/stockvalidation/StockChecker.java	Thu Oct 12 18:24:45 2017 +0200
+++ b/src/org/openbravo/retail/stockvalidation/StockChecker.java	Fri Oct 13 09:34:37 2017 +0200
@@ -4,6 +4,7 @@
 
 import javax.servlet.ServletException;
 
+import org.apache.commons.lang.StringUtils;
 import org.codehaus.jettison.json.JSONException;
 import org.codehaus.jettison.json.JSONObject;
 import org.hibernate.Query;
@@ -11,7 +12,9 @@
 import org.openbravo.base.exception.OBException;
 import org.openbravo.dal.core.OBContext;
 import org.openbravo.dal.service.OBDal;
+import org.openbravo.mobile.core.utils.OBMOBCUtils;
 import org.openbravo.retail.posterminal.JSONProcessSimple;
+import org.openbravo.retail.posterminal.utility.AttributesUtils;
 
 public class StockChecker extends JSONProcessSimple {
   @Override
@@ -20,6 +23,7 @@
     BigDecimal unitsFound = new BigDecimal(0);
     String overissueStoreBin = "";
     BigDecimal overissueQty = BigDecimal.ZERO;
+    String validatedAttrSetInstanceDescription = "";
     OBContext.setAdminMode(true);
     try {
       String orgId;
@@ -31,8 +35,12 @@
 
       jsonOrderLine = jsonData.getJSONObject("orderLine");
       jsonProduct = jsonOrderLine.getJSONObject("product");
-      if (jsonOrderLine.has("attributeValue") && !jsonOrderLine.isNull("attributeValue")) {
+      String productId = jsonProduct.getString("id");
+      if (OBMOBCUtils.isJsonObjectPropertyStringPresentNotNullAndNotEmptyString(jsonOrderLine,
+          "attributeValue")) {
         attributeValue = jsonOrderLine.getString("attributeValue");
+        validatedAttrSetInstanceDescription = AttributesUtils
+            .generateValidAttSetInstanceDescription(attributeValue, productId);
       }
       String hqlQuery = "select sum(ms.quantityOnHand-ms.reservedQty) as qtyonhand "
           + "from MaterialMgmtStorageDetail ms " + "where ms.storageBin.warehouse.id in ("
@@ -40,12 +48,16 @@
           + "ow.organization.id = :orgId) " + "and ms.product.id = :productId "
           + "and ms.quantityOnHand > 0 and ms.quantityOnHand > ms.reservedQty";
       if (attributeValue != null && !attributeValue.isEmpty())
-        hqlQuery += " and ms.attributeSetValue.description = '" + attributeValue + "'";
+        if (attributeValue != null && !attributeValue.isEmpty())
+          hqlQuery += " and ms.attributeSetValue.description = :attSetInstanceDesc";
 
       final Session session = OBDal.getInstance().getSession();
       final Query query = session.createQuery(hqlQuery);
       query.setString("orgId", orgId);
-      query.setString("productId", jsonProduct.getString("id"));
+      query.setString("productId", productId);
+      if (attributeValue != null && !attributeValue.isEmpty())
+        query.setString("attSetInstanceDesc", validatedAttrSetInstanceDescription);
+
       if (query.uniqueResult() != null) {
         unitsFound = new BigDecimal(query.uniqueResult().toString());
       } else {
@@ -56,14 +68,18 @@
         allowSell = true;
       } else {
         String hqlQueryStatus = "select ms.storageBin.id as overissueStoreBin "
-            + "from MaterialMgmtStorageDetail ms " + "where ms.storageBin.warehouse.id in ("
-            + "SELECT ow.warehouse.id " + "FROM OrganizationWarehouse as ow " + "WHERE "
-            + "ow.organization.id = :orgId) " + "and ms.product.id = :productId "
+            + "from MaterialMgmtStorageDetail ms "
+            + "where ms.storageBin.warehouse.id in ("
+            + "SELECT ow.warehouse.id "
+            + "FROM OrganizationWarehouse as ow "
+            + "WHERE "
+            + "ow.organization.id = :orgId) "
+            + "and ms.product.id = :productId "
             + "and ms.storageBin.inventoryStatus.overissue = 'Y' order by ms.storageBin.relativePriority";
         final Session sessionStatus = OBDal.getInstance().getSession();
         final Query queryStatus = sessionStatus.createQuery(hqlQueryStatus);
         queryStatus.setString("orgId", orgId);
-        queryStatus.setString("productId", jsonProduct.getString("id"));
+        queryStatus.setString("productId", productId);
         queryStatus.setMaxResults(1);
 
         if (queryStatus.uniqueResult() != null) {
@@ -71,11 +87,31 @@
           overissueQty = qtyToBuy.subtract(unitsFound);
         } else {
           overissueStoreBin = "";
+          if (StringUtils.isEmpty(overissueStoreBin)) {
+            String hqlQueryAnyOverissueBin = "select loc.id as overissueStoreBin "
+                + "from Locator loc " //
+                + "where loc.warehouse.id in (" //
+                + "  SELECT ow.warehouse.id " //
+                + "  FROM OrganizationWarehouse as ow " //
+                + "  WHERE ow.organization.id = :orgId" //
+                + "  ) " //
+                + "AND loc.inventoryStatus.overissue = 'Y' " //
+                + "ORDER BY loc.relativePriority ASC";
+            final Query queryAnyOverissueBin = OBDal.getInstance().getSession()
+                .createQuery(hqlQueryAnyOverissueBin);
+            queryAnyOverissueBin.setString("orgId", orgId);
+            queryAnyOverissueBin.setMaxResults(1);
+            if (queryAnyOverissueBin.uniqueResult() != null) {
+              overissueStoreBin = (String) queryAnyOverissueBin.uniqueResult();
+              overissueQty = BigDecimal.ZERO;
+            } else {
+              overissueStoreBin = "";
+            }
+          }
         }
       }
-
     } catch (Exception e) {
-      throw new OBException();
+      throw new OBException(e.getMessage(), true);
     } finally {
       OBContext.restorePreviousMode();
     }
diff -r 6b5524e30c63 -r e25140ad0383 web/org.openbravo.retail.stockvalidation/js/modals.js
--- a/web/org.openbravo.retail.stockvalidation/js/modals.js	Thu Oct 12 18:24:45 2017 +0200
+++ b/web/org.openbravo.retail.stockvalidation/js/modals.js	Fri Oct 13 09:34:37 2017 +0200
@@ -42,6 +42,19 @@
       }, function (data, message) {
         statusMessage.hide();
         OB.UTIL.showLoading(false);
+        if (data.exception) {
+          OB.UTIL.showConfirmation.display(OB.I18N.getLabel('OBMOBC_Error'), data.exception.message);
+          if (me.model.get('order').get('undo')) {
+            me.model.get('order').get('undo').undo(me.model);
+          } else {
+            if (data.qty <= 0) {
+              me.model.get('order').deleteLine(changedModel);
+            } else {
+              changedModel.set('qty', data.qty);
+            }
+          }
+          return true;
+        }
         if (data.allowSell === false) {
           if (data.allowNegativeStock) {
             changedModel.set('overissueStoreBin', data.overissueStoreBin, {
@@ -239,6 +252,9 @@
           lineToSend.qty = curLine.get('qty');
           lineToSend.index = index;
           lineToSend.stocked = curLine.get('product').get('stocked');
+          if (curLine.get('product').get('hasAttributes') && _.isString(curLine.get('attributeValue')) && curLine.get('attributeValue').length > 0) {
+            lineToSend.attributeValue = curLine.get('attributeValue');
+          }
           dataToSend.push(lineToSend);
         }
       }, this);

