# HG changeset patch
# User Jon Iturralde <jon.iturralde@openbravo.com>
# Date 1561371753 -7200
#      Mon Jun 24 12:22:33 2019 +0200
# Node ID 1bf2a60d15ef1cf8a981f05c5bca2b0504914f24
# Parent  50cf98e8fe7d971b43cb5fc78fa7d60d011bbb31
Fixed issue 41110: Apply Standard Filters In Discretionary Discounts
Development made by Ander Aranguren -> Added validation in case a "by total" discount is added (process failed since no lines were selected).
In that case, the process will consider that all lines are selected and check the filters for all of them.

diff -r 50cf98e8fe7d -r 1bf2a60d15ef src-db/database/sourcedata/AD_MESSAGE.xml
--- a/src-db/database/sourcedata/AD_MESSAGE.xml	Thu Jun 20 12:08:35 2019 +0200
+++ b/src-db/database/sourcedata/AD_MESSAGE.xml	Mon Jun 24 12:22:33 2019 +0200
@@ -5751,6 +5751,18 @@
 <!--785E760F36994BE9BD5CE5646807D354-->  <ISINCLUDEINI18N><![CDATA[N]]></ISINCLUDEINI18N>
 <!--785E760F36994BE9BD5CE5646807D354--></AD_MESSAGE>
 
+<!--7868A95DC33B481CA6E3B440DB6EE241--><AD_MESSAGE>
+<!--7868A95DC33B481CA6E3B440DB6EE241-->  <AD_MESSAGE_ID><![CDATA[7868A95DC33B481CA6E3B440DB6EE241]]></AD_MESSAGE_ID>
+<!--7868A95DC33B481CA6E3B440DB6EE241-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--7868A95DC33B481CA6E3B440DB6EE241-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--7868A95DC33B481CA6E3B440DB6EE241-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--7868A95DC33B481CA6E3B440DB6EE241-->  <VALUE><![CDATA[OBPOS_discountError_body]]></VALUE>
+<!--7868A95DC33B481CA6E3B440DB6EE241-->  <MSGTEXT><![CDATA[The following products are not configured for the selected discount: %0]]></MSGTEXT>
+<!--7868A95DC33B481CA6E3B440DB6EE241-->  <MSGTYPE><![CDATA[I]]></MSGTYPE>
+<!--7868A95DC33B481CA6E3B440DB6EE241-->  <AD_MODULE_ID><![CDATA[FF808181326CC34901326D53DBCF0018]]></AD_MODULE_ID>
+<!--7868A95DC33B481CA6E3B440DB6EE241-->  <ISINCLUDEINI18N><![CDATA[N]]></ISINCLUDEINI18N>
+<!--7868A95DC33B481CA6E3B440DB6EE241--></AD_MESSAGE>
+
 <!--787838BC75B041EDA793DF3F33E491CF--><AD_MESSAGE>
 <!--787838BC75B041EDA793DF3F33E491CF-->  <AD_MESSAGE_ID><![CDATA[787838BC75B041EDA793DF3F33E491CF]]></AD_MESSAGE_ID>
 <!--787838BC75B041EDA793DF3F33E491CF-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
@@ -10373,6 +10385,18 @@
 <!--D4AB908469A2466A9776E14537A371A1-->  <ISINCLUDEINI18N><![CDATA[N]]></ISINCLUDEINI18N>
 <!--D4AB908469A2466A9776E14537A371A1--></AD_MESSAGE>
 
+<!--D4F117D5AB874AE28962CD5539967950--><AD_MESSAGE>
+<!--D4F117D5AB874AE28962CD5539967950-->  <AD_MESSAGE_ID><![CDATA[D4F117D5AB874AE28962CD5539967950]]></AD_MESSAGE_ID>
+<!--D4F117D5AB874AE28962CD5539967950-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--D4F117D5AB874AE28962CD5539967950-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--D4F117D5AB874AE28962CD5539967950-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--D4F117D5AB874AE28962CD5539967950-->  <VALUE><![CDATA[OBPOS_discountError_header]]></VALUE>
+<!--D4F117D5AB874AE28962CD5539967950-->  <MSGTEXT><![CDATA[Error applying discount]]></MSGTEXT>
+<!--D4F117D5AB874AE28962CD5539967950-->  <MSGTYPE><![CDATA[I]]></MSGTYPE>
+<!--D4F117D5AB874AE28962CD5539967950-->  <AD_MODULE_ID><![CDATA[FF808181326CC34901326D53DBCF0018]]></AD_MODULE_ID>
+<!--D4F117D5AB874AE28962CD5539967950-->  <ISINCLUDEINI18N><![CDATA[N]]></ISINCLUDEINI18N>
+<!--D4F117D5AB874AE28962CD5539967950--></AD_MESSAGE>
+
 <!--D547A9EC28794C3EA64205B8854F9268--><AD_MESSAGE>
 <!--D547A9EC28794C3EA64205B8854F9268-->  <AD_MESSAGE_ID><![CDATA[D547A9EC28794C3EA64205B8854F9268]]></AD_MESSAGE_ID>
 <!--D547A9EC28794C3EA64205B8854F9268-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
diff -r 50cf98e8fe7d -r 1bf2a60d15ef web/org.openbravo.retail.posterminal/js/model/discounts.js
--- a/web/org.openbravo.retail.posterminal/js/model/discounts.js	Thu Jun 20 12:08:35 2019 +0200
+++ b/web/org.openbravo.retail.posterminal/js/model/discounts.js	Mon Jun 24 12:22:33 2019 +0200
@@ -247,6 +247,209 @@
         this.executor.nextEvent();
       }
     },
+    validateManualPromotion: function(receipt, lines, promotion, callback) {
+      var productWhereClause,
+        paramsProduct = [promotion.rule.get('id')];
+      productWhereClause = ' m_offer_id = ? and m_product_id in (';
+      if (lines && lines.models && lines.models.length === 0) {
+        lines = OB.MobileApp.model.receipt.get('lines');
+      }
+      _.each(lines.models, function(line) {
+        productWhereClause = productWhereClause + '?, ';
+        paramsProduct.push(line.get('product').get('id'));
+      });
+      productWhereClause = productWhereClause.substr(
+        0,
+        productWhereClause.length - 2
+      );
+      productWhereClause = productWhereClause + ')';
+
+      var errorCallback = function() {
+        OB.UTIL.showConfirmation.display(
+          OB.I18N.getLabel('Error'),
+          OB.I18N.getLabel('SearchQueryError'),
+          [
+            {
+              label: OB.I18N.getLabel('OBMOBC_LblOk'),
+              isConfirmButton: true
+            }
+          ]
+        );
+      };
+
+      var showMessage = function(product) {
+        var products = '';
+        _.each(product.models, function(prod) {
+          products = products + prod.get('_identifier') + ', ';
+        });
+        products = products.substr(0, products.length - 2);
+        OB.UTIL.showConfirmation.display(
+          OB.I18N.getLabel('OBPOS_discountError_header'),
+          OB.I18N.getLabel('OBPOS_discountError_body', [products]),
+          [
+            {
+              label: OB.I18N.getLabel('OBMOBC_LblOk'),
+              isConfirmButton: true,
+              action: function() {
+                return true;
+              }
+            }
+          ]
+        );
+      };
+
+      var checkCategory = function(productToCheck) {
+        var paramsCategory = [],
+          categoryWhereClause = 'm_offer_id = ? and m_product_category_id in (';
+        paramsCategory = [promotion.rule.get('id')];
+        _.each(lines.models, function(line) {
+          _.each(productToCheck, function(product) {
+            if (line.get('product').get('id') === product) {
+              paramsCategory.push(line.get('product').get('productCategory'));
+              categoryWhereClause = categoryWhereClause + '?, ';
+            }
+          });
+        });
+        categoryWhereClause = categoryWhereClause.substr(
+          0,
+          categoryWhereClause.length - 2
+        );
+        categoryWhereClause = categoryWhereClause + ')';
+        // Query to check Product Categories
+        OB.Dal.query(
+          OB.Model.DiscountFilterProductCategory,
+          'select distinct m_product_category_id from m_offer_prod_cat where ' +
+            categoryWhereClause,
+          paramsCategory,
+          function(records) {
+            paramsCategory.shift(0);
+            var categoryNotValid,
+              productWhereClause = '',
+              categoryWhereClause = '',
+              params = [],
+              categories = [];
+            _.each(records.models, function(category) {
+              categories.push(category.get('productCategory'));
+            });
+            categoryNotValid = _.difference(paramsCategory, categories);
+            _.each(productToCheck, function(product) {
+              params.push(product);
+              productWhereClause = productWhereClause + '?, ';
+            });
+            productWhereClause = productWhereClause.substr(
+              0,
+              productWhereClause.length - 2
+            );
+            _.each(categoryNotValid, function(category) {
+              params.push(category);
+              categoryWhereClause = categoryWhereClause + '?, ';
+            });
+            categoryWhereClause = categoryWhereClause.substr(
+              0,
+              categoryWhereClause.length - 2
+            );
+            if (
+              promotion &&
+              promotion.rule.get('includedProductCategories') === 'N' &&
+              categories.length < productToCheck.length
+            ) {
+              OB.Dal.query(
+                OB.Model.DiscountFilterProductCategory,
+                'select * from m_product where m_product_id in (' +
+                  productWhereClause +
+                  ') and m_product_category_id in (' +
+                  categoryWhereClause +
+                  ')',
+                params,
+                function(records) {
+                  showMessage(records);
+                  return;
+                },
+                errorCallback
+              );
+            } else if (
+              promotion &&
+              promotion.rule.get('includedProductCategories') === 'Y' &&
+              categories.length !== 0
+            ) {
+              OB.Dal.query(
+                OB.Model.DiscountFilterProductCategory,
+                'select * from m_product where m_product_id in (' +
+                  productWhereClause +
+                  ') and m_product_category_id not in (' +
+                  categoryWhereClause +
+                  ')',
+                params,
+                function(records) {
+                  showMessage(records);
+                  return;
+                },
+                errorCallback
+              );
+            } else {
+              callback();
+            }
+          },
+          errorCallback
+        );
+      };
+
+      // Query to check Products
+      OB.Dal.query(
+        OB.Model.DiscountFilterProduct,
+        'select distinct m_product_id from m_offer_product where ' +
+          productWhereClause,
+        paramsProduct,
+        function(records) {
+          paramsProduct.shift(0);
+          var products = [],
+            productToCheck;
+          _.each(records.models, function(record) {
+            products.push(record.get('product'));
+          });
+          productToCheck = _.difference(paramsProduct, products);
+          // If Product filter is "Only those defined" ==> 'N' or All excluding defined ==> 'Y'
+          if (
+            promotion &&
+            promotion.rule.get('includedProducts') === 'N' &&
+            productToCheck.length !== 0
+          ) {
+            checkCategory(productToCheck);
+          } else if (
+            promotion &&
+            promotion.rule.get('includedProducts') === 'Y'
+          ) {
+            if (products.length > 0) {
+              productWhereClause = '';
+              _.each(products, function(prod) {
+                productWhereClause = productWhereClause + '?, ';
+              });
+              productWhereClause = productWhereClause.substr(
+                0,
+                productWhereClause.length - 2
+              );
+              productWhereClause = productWhereClause + ')';
+              OB.Dal.query(
+                OB.Model.DiscountFilterProductCategory,
+                'select * from m_product where m_product_id in (' +
+                  productWhereClause,
+                products,
+                function(records) {
+                  showMessage(records);
+                  return;
+                },
+                errorCallback
+              );
+            } else {
+              checkCategory(productToCheck);
+            }
+          } else {
+            callback();
+          }
+        },
+        errorCallback
+      );
+    },
 
     addManualPromotion: function(receipt, lines, promotion) {
       var rule =
diff -r 50cf98e8fe7d -r 1bf2a60d15ef web/org.openbravo.retail.posterminal/js/pointofsale/view/ticketdiscount.js
--- a/web/org.openbravo.retail.posterminal/js/pointofsale/view/ticketdiscount.js	Thu Jun 20 12:08:35 2019 +0200
+++ b/web/org.openbravo.retail.posterminal/js/pointofsale/view/ticketdiscount.js	Mon Jun 24 12:22:33 2019 +0200
@@ -464,44 +464,61 @@
       discountsContainer = this.$.discountsContainer,
       orderLinesCollection = new OB.Collection.OrderLineList(),
       me = this;
-    //preApplyDiscountsHook
-    OB.UTIL.HookManager.executeHooks(
-      'OBPOS_preApplyDiscountsHook',
-      {
-        context: this
-      },
-      function(args) {
-        if (args && args.cancelOperation) {
-          me.closingDiscounts();
-          return;
-        }
-        promotionToAplly.rule = discountsContainer.model;
-        promotionToAplly.definition = {};
-        promotionToAplly.definition.userAmt = discountsContainer.amt;
-        promotionToAplly.definition.applyNext = !me.$.checkOverride.checked;
-        promotionToAplly.definition.lastApplied = true;
-        promotionToAplly.definition.obdiscLineFinalgross =
-          discountsContainer.amt;
+    _.each(me.checkedLines, function(line) {
+      orderLinesCollection.add(line);
+    });
+    promotionToAplly.rule = discountsContainer.model;
+    promotionToAplly.definition = {};
+    promotionToAplly.definition.userAmt = discountsContainer.amt;
+    promotionToAplly.definition.applyNext = !me.$.checkOverride.checked;
+    promotionToAplly.definition.lastApplied = true;
+
+    var callback = function() {
+      var discountsContainer = me.$.discountsContainer;
+      //preApplyDiscountsHook
+      OB.UTIL.HookManager.executeHooks(
+        'OBPOS_preApplyDiscountsHook',
+        {
+          context: me
+        },
+        function(args) {
+          if (args && args.cancelOperation) {
+            me.closingDiscounts();
+            return;
+          }
+          promotionToAplly.rule = discountsContainer.model;
+          promotionToAplly.definition = {};
+          promotionToAplly.definition.userAmt = discountsContainer.amt;
+          promotionToAplly.definition.applyNext = !me.$.checkOverride.checked;
+          promotionToAplly.definition.lastApplied = true;
 
-        if (discountsContainer.requiresQty && !discountsContainer.amt) {
-          //Show a modal pop up with the error
-          me.doShowPopup({
-            popup: 'modalDiscountNeedQty'
+          if (discountsContainer.requiresQty && !discountsContainer.amt) {
+            //Show a modal pop up with the error
+            me.doShowPopup({
+              popup: 'modalDiscountNeedQty'
+            });
+            return true;
+          }
+
+          _.each(me.checkedLines, function(line) {
+            orderLinesCollection.add(line);
           });
-          return true;
+          OB.Model.Discounts.addManualPromotion(
+            me.order,
+            orderLinesCollection,
+            promotionToAplly
+          );
+
+          me.closingDiscounts();
         }
-        _.each(me.checkedLines, function(line) {
-          orderLinesCollection.add(line);
-        });
+      );
+    };
 
-        OB.Model.Discounts.addManualPromotion(
-          me.order,
-          orderLinesCollection,
-          promotionToAplly
-        );
-
-        me.closingDiscounts();
-      }
+    OB.Model.Discounts.validateManualPromotion(
+      me.order,
+      orderLinesCollection,
+      promotionToAplly,
+      callback
     );
   },
   init: function(model) {
