commit e452363095397adf1a4d49913c3de3e73b72fb0b
Author: Adrián Romero <adrian.romero@openbravo.com>
Date:   Wed Mar 4 14:18:00 2020 +0100

    Fixes ISSUE-0043415: Selfcheckout must include provider groups functionality to be aligned with POS

diff --git a/src-db/database/sourcedata/AD_FIELD.xml b/src-db/database/sourcedata/AD_FIELD.xml
index 388e78a..6a08b37 100644
--- a/src-db/database/sourcedata/AD_FIELD.xml
+++ b/src-db/database/sourcedata/AD_FIELD.xml
@@ -498,7 +498,7 @@
 <!--7DB94E8210E0466AB8E86349406A128D-->  <IGNOREINWAD><![CDATA[N]]></IGNOREINWAD>
 <!--7DB94E8210E0466AB8E86349406A128D-->  <AD_FIELDGROUP_ID><![CDATA[8B843BFAC4E34DCF97701EF464DD0D4F]]></AD_FIELDGROUP_ID>
 <!--7DB94E8210E0466AB8E86349406A128D-->  <ISDISPLAYED><![CDATA[Y]]></ISDISPLAYED>
-<!--7DB94E8210E0466AB8E86349406A128D-->  <DISPLAYLOGIC><![CDATA[@OBSCO_PaymentTypeSCO@='Y']]></DISPLAYLOGIC>
+<!--7DB94E8210E0466AB8E86349406A128D-->  <DISPLAYLOGIC><![CDATA[@OBSCO_PaymentTypeSCO@='Y' & (@Obpos_Paymentgroup_ID@='0' | @Obpos_Paymentgroup_ID@='' )]]></DISPLAYLOGIC>
 <!--7DB94E8210E0466AB8E86349406A128D-->  <DISPLAYLENGTH><![CDATA[60]]></DISPLAYLENGTH>
 <!--7DB94E8210E0466AB8E86349406A128D-->  <ISREADONLY><![CDATA[N]]></ISREADONLY>
 <!--7DB94E8210E0466AB8E86349406A128D-->  <SEQNO><![CDATA[510]]></SEQNO>
diff --git a/src/org/openbravo/retail/selfcheckout/SCOComponentProvider.java b/src/org/openbravo/retail/selfcheckout/SCOComponentProvider.java
index da732a8..f1d3428 100644
--- a/src/org/openbravo/retail/selfcheckout/SCOComponentProvider.java
+++ b/src/org/openbravo/retail/selfcheckout/SCOComponentProvider.java
@@ -1,6 +1,6 @@
 /*
  ************************************************************************************
- * Copyright (C) 2017-2019 Openbravo S.L.U.
+ * Copyright (C) 2017-2020 Openbravo S.L.U.
  * Licensed under the Openbravo Commercial License version 1.0
  * You may obtain a copy of the License at http://www.openbravo.com/legal/obcl.html
  * or in the legal folder of this module distribution.
@@ -74,6 +74,7 @@ public class SCOComponentProvider extends BaseComponentProvider {
     jsResourceDependency.add("components/baseAction.js");
     jsResourceDependency.add("components/stepAction.js");
     jsResourceDependency.add("components/basePanel.js");
+    jsResourceDependency.add("components/providerGroupPanel.js");
     jsResourceDependency.add("components/windowView.js");
     jsResourceDependency.add("components/header.js");
     jsResourceDependency.add("components/toolbarRight.js");
@@ -112,6 +113,7 @@ public class SCOComponentProvider extends BaseComponentProvider {
     jsResourceDependency.add("panels/salesAssistantPanel.js");
     jsResourceDependency.add("panels/selectPaymentPanel.js");
     jsResourceDependency.add("panels/mockPaymentPanel.js");
+    jsResourceDependency.add("panels/mockProviderPanel.js");
     jsResourceDependency.add("panels/scanProductPanel.js");
     jsResourceDependency.add("panels/verifyProductPanel.js");
     jsResourceDependency.add("panels/placeProductPanel.js");
@@ -137,6 +139,7 @@ public class SCOComponentProvider extends BaseComponentProvider {
     jsResourceDependency.add("steps/salesAssistant.js");
     jsResourceDependency.add("steps/selectPayment.js");
     jsResourceDependency.add("steps/mockPayment.js");
+    jsResourceDependency.add("steps/mockProvider.js");
     jsResourceDependency.add("steps/paymentError.js");
     jsResourceDependency.add("steps/scanProduct.js");
     jsResourceDependency.add("steps/verifyProduct.js");
@@ -164,6 +167,7 @@ public class SCOComponentProvider extends BaseComponentProvider {
     jsResourceDependency.add("actions/doSalesAssistant.js");
     jsResourceDependency.add("actions/doSelectPayment.js");
     jsResourceDependency.add("actions/doPaymentProvider.js");
+    jsResourceDependency.add("actions/doProviderGroup.js");
     jsResourceDependency.add("actions/doPrintResult.js");
     jsResourceDependency.add("actions/doScanProduct.js");
     jsResourceDependency.add("actions/doVerifyProduct.js");
diff --git a/src/org/openbravo/retail/selfcheckout/SCOInitialValidation.java b/src/org/openbravo/retail/selfcheckout/SCOInitialValidation.java
index 435ae23..f962eae 100644
--- a/src/org/openbravo/retail/selfcheckout/SCOInitialValidation.java
+++ b/src/org/openbravo/retail/selfcheckout/SCOInitialValidation.java
@@ -29,7 +29,8 @@ public class SCOInitialValidation extends CustomInitialValidation {
     }
 
     final String whereclausePaymentProvider = " as e where e.active is true and e.obposTerminaltype.obscoIsSCO is true "
-        + "and e.obposTerminaltype=:terminalType and e.oBSCOPaymentProvider is null";
+        + "and e.obposTerminaltype=:terminalType and "
+        + "e.oBSCOPaymentProvider is null and (e.obposPaymentgroup is null or e.obposPaymentgroup.id = '0')";
     OBQuery<TerminalTypePaymentMethod> queryPaymentProvider = OBDal.getInstance()
         .createQuery(TerminalTypePaymentMethod.class, whereclausePaymentProvider);
     queryPaymentProvider.setNamedParameter("terminalType", posTerminal.getObposTerminaltype());
diff --git a/src/org/openbravo/retail/selfcheckout/eventHandler/PaymentTypeEventHandler.java b/src/org/openbravo/retail/selfcheckout/eventHandler/PaymentTypeEventHandler.java
index eca3cd7..c7c154a 100644
--- a/src/org/openbravo/retail/selfcheckout/eventHandler/PaymentTypeEventHandler.java
+++ b/src/org/openbravo/retail/selfcheckout/eventHandler/PaymentTypeEventHandler.java
@@ -1,6 +1,6 @@
 /*
  ************************************************************************************
- * Copyright (C) 2017 Openbravo S.L.U.
+ * Copyright (C) 2017-2020 Openbravo S.L.U.
  * Licensed under the Openbravo Commercial License version 1.0
  * You may obtain a copy of the License at http://www.openbravo.com/legal/obcl.html
  * or in the legal folder of this module distribution.
@@ -46,7 +46,9 @@ public class PaymentTypeEventHandler extends EntityPersistenceEventObserver {
       if (paymentType.isCash()) {
         throw new OBException("@OBSCO_CashPayment@");
       }
-      if (paymentType.getOBSCOPaymentProvider() == null) {
+      if (paymentType.getOBSCOPaymentProvider() == null
+          && (paymentType.getObposPaymentgroup() == null
+              || "0".equals(paymentType.getObposPaymentgroup().getId()))) {
         throw new OBException("@OBSCO_MissingProvider@");
       }
     }
diff --git a/web/org.openbravo.retail.selfcheckout/source/actions/doProviderGroup.js b/web/org.openbravo.retail.selfcheckout/source/actions/doProviderGroup.js
new file mode 100644
index 0000000..1dfc2f4
--- /dev/null
+++ b/web/org.openbravo.retail.selfcheckout/source/actions/doProviderGroup.js
@@ -0,0 +1,27 @@
+/*
+ ************************************************************************************
+ * Copyright (C) 2020 Openbravo S.L.U.
+ * Licensed under the Openbravo Commercial License version 1.0
+ * You may obtain a copy of the License at http://www.openbravo.com/legal/obcl.html
+ * or in the legal folder of this module distribution.
+ ************************************************************************************
+ */
+
+/*global enyo*/
+
+// This is the action invoked by the Select Payment step
+// It sets the selected payment method data and goes to its the payment provider step
+enyo.kind({
+  name: 'OB.SCO.APP.ACTION.DoProviderGroup',
+  kind: 'OB.SCO.StepAction',
+  eventName: 'GoProviderGroup',
+  stepName: null,
+  // 'SelectPayment',
+  calculateStep: function(data) {
+    // in: event, state, receipt
+    // out: state, receipt, nextStep
+    const providerGroup = data.event.providerGroup;
+    data.state.set('selectedProviderGroup', providerGroup);
+    data.nextStep = providerGroup.provider + 'SCO';
+  }
+});
diff --git a/web/org.openbravo.retail.selfcheckout/source/components/providerGroupPanel.js b/web/org.openbravo.retail.selfcheckout/source/components/providerGroupPanel.js
new file mode 100644
index 0000000..cb1bc8e
--- /dev/null
+++ b/web/org.openbravo.retail.selfcheckout/source/components/providerGroupPanel.js
@@ -0,0 +1,96 @@
+/*
+ ************************************************************************************
+ * Copyright (C) 2020 Openbravo S.L.U.
+ * Licensed under the Openbravo Commercial License version 1.0
+ * You may obtain a copy of the License at http://www.openbravo.com/legal/obcl.html
+ * or in the legal folder of this module distribution.
+ ************************************************************************************
+ */
+
+/*global  enyo */
+{
+  enyo.kind({
+    name: 'OB.SCO.ProviderGroupPanel',
+    kind: 'OB.SCO.BasePanel',
+    getProviderGroup: function() {
+      // This function can be overwritten in case payment button is not a provider group
+      return this.state.get('selectedProviderGroup');
+    },
+    getFirstPayment: function() {
+      const providerGroup = this.getProviderGroup();
+      const payments = OB.MobileApp.model.get('payments');
+      return payments.find(
+        payment =>
+          payment.providerGroup && payment.providerGroup.id === providerGroup.id
+      );
+    },
+    createPaymentInfo: function() {
+      const receipt = this.receipt;
+      const firstPayment = this.getFirstPayment();
+      return {
+        receipt: receipt,
+        currency: firstPayment.isocode,
+        amount: receipt.getPending(),
+        refund: receipt.getPaymentStatus().isNegative,
+        providerGroup: this.getProviderGroup()
+      };
+    },
+    createReceiptPayment: function(paymentinfo, response) {
+      const processedAmount = response.properties.processedAmount
+        ? response.properties.processedAmount
+        : paymentinfo.amount;
+      const payments = OB.MobileApp.model.get('payments');
+      const addResponseToPayment = payment => {
+        // We found the payment method that applies.
+        const paymentline = {
+          kind: payment.payment.searchKey,
+          name: payment.payment._identifier,
+          amount: processedAmount,
+          rate: payment.rate,
+          mulrate: payment.mulrate,
+          isocode: payment.isocode,
+          allowOpenDrawer: payment.paymentMethod.allowopendrawer,
+          isCash: payment.paymentMethod.iscash,
+          openDrawer: payment.paymentMethod.openDrawer,
+          printtwice: payment.paymentMethod.printtwice,
+          paymentData: {
+            provider: paymentinfo.providerGroup.provider,
+            voidConfirmation: false,
+            // Is the void provider in charge of defining confirmation.
+            transaction: response.transaction,
+            authorization: response.authorization,
+            properties: response.properties
+          }
+        };
+        paymentinfo.receipt.addPayment(new OB.Model.PaymentLine(paymentline));
+      };
+
+      // First attempt. Find an exact match.
+      const cardlogo = response.properties.cardlogo;
+      let undefinedPayment = null;
+      for (let payment of payments) {
+        if (
+          payment.providerGroup &&
+          payment.providerGroup.id === paymentinfo.providerGroup.id &&
+          cardlogo === payment.paymentType.searchKey
+        ) {
+          addResponseToPayment(payment);
+          return; // Success
+        } else if (
+          payment.paymentType &&
+          'UNDEFINED' === payment.paymentType.searchKey
+        ) {
+          undefinedPayment = payment;
+        }
+      }
+
+      // Second attempt. Find UNDEFINED paymenttype.
+      if (undefinedPayment) {
+        addResponseToPayment(undefinedPayment);
+        return; // Success
+      }
+
+      throw { message: 'Cannot find configured payment method' };
+    }
+  });
+}
diff --git a/web/org.openbravo.retail.selfcheckout/source/panels/mockProviderPanel.js b/web/org.openbravo.retail.selfcheckout/source/panels/mockProviderPanel.js
new file mode 100644
index 0000000..8681745
--- /dev/null
+++ b/web/org.openbravo.retail.selfcheckout/source/panels/mockProviderPanel.js
@@ -0,0 +1,66 @@
+/*
+ ************************************************************************************
+ * Copyright (C) 2020 Openbravo S.L.U.
+ * Licensed under the Openbravo Commercial License version 1.0
+ * You may obtain a copy of the License at http://www.openbravo.com/legal/obcl.html
+ * or in the legal folder of this module distribution.
+ ************************************************************************************
+ */
+
+/*global  enyo */
+{
+  enyo.kind({
+    name: 'OB.SCO.APP.PANELRIGHT.MockProviderPanel',
+    kind: 'OB.SCO.ProviderGroupPanel',
+    classes: 'scoMainArea',
+    components: [
+      {
+        name: 'informationArea',
+        classes: 'scoInformationArea',
+        components: [
+          {
+            name: 'welcometext',
+            classes: 'scoMainLabel',
+            content: 'This is the skeleton of the Mock Provider Group panel'
+          },
+          {
+            classes: 'scoButtonsArea',
+            components: [
+              {
+                name: 'back',
+                kind: 'OB.SCO.ButtonComposedBackwardType1',
+                i18nLabel: 'OBSCO_Back',
+                ontap: 'actionBack'
+              },
+              {
+                name: 'pay',
+                kind: 'OB.SCO.ButtonComposedForwardType1',
+                i18nLabel: 'OBSCO_Pay',
+                ontap: 'actionPay'
+              }
+            ]
+          }
+        ]
+      }
+    ],
+    actionBack: function(inSender, inEvent) {
+      OB.SCO.Utils.completeProcess(this);
+    },
+    actionPay: function(inSender, inEvent) {
+      const paymentinfo = this.createPaymentInfo();
+      const response = this.processPayment(paymentinfo);
+      this.createReceiptPayment(paymentinfo, response);
+      OB.SCO.Utils.completeProcess(this);
+    },
+    processPayment: function(paymentinfo) {
+      return {
+        properties: {
+          cardlogo: 'MASTER',
+          cardNumber: '***********1234'
+        },
+        transaction: 'T12345',
+        authorization: 'A12345'
+      };
+    }
+  });
+}
diff --git a/web/org.openbravo.retail.selfcheckout/source/panels/selectPaymentPanel.js b/web/org.openbravo.retail.selfcheckout/source/panels/selectPaymentPanel.js
index bde9676..a4ff2a7 100644
--- a/web/org.openbravo.retail.selfcheckout/source/panels/selectPaymentPanel.js
+++ b/web/org.openbravo.retail.selfcheckout/source/panels/selectPaymentPanel.js
@@ -1,6 +1,6 @@
 /*
  ************************************************************************************
- * Copyright (C) 2017-2019 Openbravo S.L.U.
+ * Copyright (C) 2017-2020 Openbravo S.L.U.
  * Licensed under the Openbravo Commercial License version 1.0
  * You may obtain a copy of the License at http://www.openbravo.com/legal/obcl.html
  * or in the legal folder of this module distribution.
@@ -43,23 +43,40 @@ enyo.kind({
   initComponents: function() {
     this.inherited(arguments);
 
-    var payments = OB.MobileApp.model.get('payments');
-    var button;
+    const payments = OB.MobileApp.model.get('payments');
+    const groupsrendered = {};
 
-    payments.forEach(function(payment, index) {
-      button = this.$.paymentsArea.createComponent(
-        {
+    payments.forEach((payment, index) => {
+      let buttoncomponent;
+      if (payment.providerGroup && payment.providerGroup.id !== '0') {
+        if (groupsrendered[payment.providerGroup.id]) {
+          return;
+        }
+        buttoncomponent = {
+          name: 'paymentgroup-' + index,
+          kind: 'OB.SCO.ButtonPayment',
+          buttonContent: payment.providerGroup._identifier,
+          buttonImage: payment.providerGroup.image,
+          providerGroup: payment.providerGroup,
+          ontap: 'selectProviderGroup'
+        };
+        groupsrendered[payment.providerGroup.id] = true;
+      } else {
+        buttoncomponent = {
           name: 'payment-' + index,
           kind: 'OB.SCO.ButtonPayment',
+          buttonContent: payment.payment._identifier,
+          buttonImage: payment.image,
           payment: payment,
           ontap: 'selectPayment'
-        },
-        {
+        };
+      }
+      this.$.paymentsArea
+        .createComponent(buttoncomponent, {
           owner: this
-        }
-      );
-      button.render();
-    }, this);
+        })
+        .render();
+    });
   },
   show: function() {
     this.inherited(arguments);
@@ -75,6 +92,12 @@ enyo.kind({
       payment: inSender.payment
     });
   },
+  selectProviderGroup: function(inSender, inEvent) {
+    this.executeEvent({
+      name: 'GoProviderGroup',
+      providerGroup: inSender.providerGroup
+    });
+  },
   actionBack: function(inSender, inEvent) {
     this.executeEvent({
       name: 'GoScanProduct'
@@ -102,10 +125,10 @@ enyo.kind({
   ],
   initComponents: function() {
     this.inherited(arguments);
-    this.$.buttonLabel.setContent(this.payment.payment._identifier);
-    if (this.payment.image) {
+    this.$.buttonLabel.setContent(this.buttonContent);
+    if (this.buttonImage) {
       this.$.buttonImage.setStyle(
-        'background-image: url(' + this.payment.image + ');'
+        'background-image: url(' + this.buttonImage + ');'
       );
     } else {
       this.$.buttonImage.addClass('scoPaymentButton_imgBg-imgNotAvailable');
diff --git a/web/org.openbravo.retail.selfcheckout/source/steps/mockProvider.js b/web/org.openbravo.retail.selfcheckout/source/steps/mockProvider.js
new file mode 100644
index 0000000..0c05a4e
--- /dev/null
+++ b/web/org.openbravo.retail.selfcheckout/source/steps/mockProvider.js
@@ -0,0 +1,23 @@
+/*
+ ************************************************************************************
+ * Copyright (C) 2020 Openbravo S.L.U.
+ * Licensed under the Openbravo Commercial License version 1.0
+ * You may obtain a copy of the License at http://www.openbravo.com/legal/obcl.html
+ * or in the legal folder of this module distribution.
+ ************************************************************************************
+ */
+
+/*global enyo*/
+
+enyo.kind({
+  name: 'OB.SCO.APP.STEP.OBPOS_MockProviderSCO',
+  kind: 'OB.SCO.DefaultStep',
+  leftPanel: 'Receipt',
+  rightPanel: 'MockProviderPanel',
+  // Properties
+  showDocumentNo: true,
+  showLanguagesToolbar: false,
+  allowDeleteLines: false,
+  rfidEnabled: false,
+  barcodeEnabled: false
+});
