diff -r 25d8c134dbd4 src-db/database/sourcedata/AD_MESSAGE.xml
--- a/src-db/database/sourcedata/AD_MESSAGE.xml	Mon Nov 06 05:45:35 2017 +0000
+++ b/src-db/database/sourcedata/AD_MESSAGE.xml	Fri Nov 17 14:31:41 2017 +0100
@@ -1718,6 +1718,18 @@
 <!--2FD9FDEE3A8F47BCA0C4A2826F738577-->  <ISINCLUDEINI18N><![CDATA[N]]></ISINCLUDEINI18N>
 <!--2FD9FDEE3A8F47BCA0C4A2826F738577--></AD_MESSAGE>
 
+<!--3044FEE155334CE7B0A587092F1215C0--><AD_MESSAGE>
+<!--3044FEE155334CE7B0A587092F1215C0-->  <AD_MESSAGE_ID><![CDATA[3044FEE155334CE7B0A587092F1215C0]]></AD_MESSAGE_ID>
+<!--3044FEE155334CE7B0A587092F1215C0-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--3044FEE155334CE7B0A587092F1215C0-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--3044FEE155334CE7B0A587092F1215C0-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--3044FEE155334CE7B0A587092F1215C0-->  <VALUE><![CDATA[OBPOS_AttributeValueMissing]]></VALUE>
+<!--3044FEE155334CE7B0A587092F1215C0-->  <MSGTEXT><![CDATA[missing]]></MSGTEXT>
+<!--3044FEE155334CE7B0A587092F1215C0-->  <MSGTYPE><![CDATA[I]]></MSGTYPE>
+<!--3044FEE155334CE7B0A587092F1215C0-->  <AD_MODULE_ID><![CDATA[FF808181326CC34901326D53DBCF0018]]></AD_MODULE_ID>
+<!--3044FEE155334CE7B0A587092F1215C0-->  <ISINCLUDEINI18N><![CDATA[N]]></ISINCLUDEINI18N>
+<!--3044FEE155334CE7B0A587092F1215C0--></AD_MESSAGE>
+
 <!--310B20BEEC204FA1B83FFDFEC6ADEC59--><AD_MESSAGE>
 <!--310B20BEEC204FA1B83FFDFEC6ADEC59-->  <AD_MESSAGE_ID><![CDATA[310B20BEEC204FA1B83FFDFEC6ADEC59]]></AD_MESSAGE_ID>
 <!--310B20BEEC204FA1B83FFDFEC6ADEC59-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
@@ -4696,6 +4708,18 @@
 <!--849E52825027454DA2FFA882AA093614-->  <ISINCLUDEINI18N><![CDATA[N]]></ISINCLUDEINI18N>
 <!--849E52825027454DA2FFA882AA093614--></AD_MESSAGE>
 
+<!--85382A0522BE4910A41631AB40B3CD2C--><AD_MESSAGE>
+<!--85382A0522BE4910A41631AB40B3CD2C-->  <AD_MESSAGE_ID><![CDATA[85382A0522BE4910A41631AB40B3CD2C]]></AD_MESSAGE_ID>
+<!--85382A0522BE4910A41631AB40B3CD2C-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--85382A0522BE4910A41631AB40B3CD2C-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--85382A0522BE4910A41631AB40B3CD2C-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--85382A0522BE4910A41631AB40B3CD2C-->  <VALUE><![CDATA[OBPOS_openAttributes]]></VALUE>
+<!--85382A0522BE4910A41631AB40B3CD2C-->  <MSGTEXT><![CDATA[Attributes]]></MSGTEXT>
+<!--85382A0522BE4910A41631AB40B3CD2C-->  <MSGTYPE><![CDATA[I]]></MSGTYPE>
+<!--85382A0522BE4910A41631AB40B3CD2C-->  <AD_MODULE_ID><![CDATA[FF808181326CC34901326D53DBCF0018]]></AD_MODULE_ID>
+<!--85382A0522BE4910A41631AB40B3CD2C-->  <ISINCLUDEINI18N><![CDATA[N]]></ISINCLUDEINI18N>
+<!--85382A0522BE4910A41631AB40B3CD2C--></AD_MESSAGE>
+
 <!--8576738EC2F44ECBB683D808E462E5C0--><AD_MESSAGE>
 <!--8576738EC2F44ECBB683D808E462E5C0-->  <AD_MESSAGE_ID><![CDATA[8576738EC2F44ECBB683D808E462E5C0]]></AD_MESSAGE_ID>
 <!--8576738EC2F44ECBB683D808E462E5C0-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
@@ -7589,6 +7613,18 @@
 <!--D2B84F6EECCC407AB521128A71B42955-->  <ISINCLUDEINI18N><![CDATA[N]]></ISINCLUDEINI18N>
 <!--D2B84F6EECCC407AB521128A71B42955--></AD_MESSAGE>
 
+<!--D2C6A0EFE64C44008B144E99CBA8BD21--><AD_MESSAGE>
+<!--D2C6A0EFE64C44008B144E99CBA8BD21-->  <AD_MESSAGE_ID><![CDATA[D2C6A0EFE64C44008B144E99CBA8BD21]]></AD_MESSAGE_ID>
+<!--D2C6A0EFE64C44008B144E99CBA8BD21-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--D2C6A0EFE64C44008B144E99CBA8BD21-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--D2C6A0EFE64C44008B144E99CBA8BD21-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--D2C6A0EFE64C44008B144E99CBA8BD21-->  <VALUE><![CDATA[OBPOS_AllAttributesNeedValue]]></VALUE>
+<!--D2C6A0EFE64C44008B144E99CBA8BD21-->  <MSGTEXT><![CDATA[There are lines missing to set the attribute value]]></MSGTEXT>
+<!--D2C6A0EFE64C44008B144E99CBA8BD21-->  <MSGTYPE><![CDATA[I]]></MSGTYPE>
+<!--D2C6A0EFE64C44008B144E99CBA8BD21-->  <AD_MODULE_ID><![CDATA[FF808181326CC34901326D53DBCF0018]]></AD_MODULE_ID>
+<!--D2C6A0EFE64C44008B144E99CBA8BD21-->  <ISINCLUDEINI18N><![CDATA[N]]></ISINCLUDEINI18N>
+<!--D2C6A0EFE64C44008B144E99CBA8BD21--></AD_MESSAGE>
+
 <!--D387B80B40A945B89B84255FFAD2076A--><AD_MESSAGE>
 <!--D387B80B40A945B89B84255FFAD2076A-->  <AD_MESSAGE_ID><![CDATA[D387B80B40A945B89B84255FFAD2076A]]></AD_MESSAGE_ID>
 <!--D387B80B40A945B89B84255FFAD2076A-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
diff -r 25d8c134dbd4 src/org/openbravo/retail/posterminal/OrderLoader.java
--- a/src/org/openbravo/retail/posterminal/OrderLoader.java	Mon Nov 06 05:45:35 2017 +0000
+++ b/src/org/openbravo/retail/posterminal/OrderLoader.java	Fri Nov 17 14:31:41 2017 +0100
@@ -338,6 +338,7 @@
             }
           }
         } else if (!newLayaway && (creditpaidLayaway || fullypaidLayaway)) {
+
           order = OBDal.getInstance().get(Order.class, jsonorder.getString("id"));
           order.setObposAppCashup(jsonorder.getString("obposAppCashup"));
           order.setDelivered(true);
@@ -391,6 +392,10 @@
           }
         }
 
+        // 37240: done outside of createOrderLines, since needs to be done in all order loaders, not
+        // only in new ones
+        updateLinesWithAttributes(order, orderlines, lineReferences);
+
         if (log.isDebugEnabled()) {
           t113 = System.currentTimeMillis();
         }
@@ -555,6 +560,30 @@
     }
   }
 
+  private void updateLinesWithAttributes(Order order, JSONArray orderlines,
+      ArrayList<OrderLine> lineReferences) throws JSONException {
+    for (int i = 0; i < orderlines.length(); i++) {
+      OrderLine orderline = order.getOrderLineList().get(i);
+
+      if (orderline.getProduct().getAttributeSet() == null) {
+        continue;
+      }
+      JSONObject jsonOrderLine = orderlines.getJSONObject(i);
+      String attr = null;
+      if (jsonOrderLine.has("attSetInstanceDesc")) {
+        attr = jsonOrderLine.get("attSetInstanceDesc").toString();
+      } else if (jsonOrderLine.has("attributeValue")) {
+        attr = jsonOrderLine.get("attributeValue").toString();
+      }
+      if (attr.equals("null")) {
+        attr = null;
+      }
+      orderline.setAttributeSetValue(AttributesUtils.fetchAttributeSetValue(attr, jsonOrderLine
+          .getJSONObject("product").get("id").toString()));
+
+    }
+  }
+
   private void mergeDeletedLines(JSONObject jsonorder) {
     try {
       JSONArray deletedLines = jsonorder.getJSONArray("deletedLines");
@@ -1329,17 +1358,6 @@
         // shipment is created or is a C&R and is not a layaway, so all is delivered
         orderline.setDeliveredQuantity(orderline.getOrderedQuantity());
       }
-      if (OBMOBCUtils.isJsonObjectPropertyStringPresentNotNullAndNotEmptyString(jsonOrderLine,
-          "attSetInstanceDesc")) {
-        orderline.setAttributeSetValue(AttributesUtils.fetchAttributeSetValue(
-            jsonOrderLine.get("attSetInstanceDesc").toString(),
-            jsonOrderLine.getJSONObject("product").get("id").toString()));
-      } else if (OBMOBCUtils.isJsonObjectPropertyStringPresentNotNullAndNotEmptyString(
-          jsonOrderLine, "attributeValue")) {
-        orderline.setAttributeSetValue(AttributesUtils.fetchAttributeSetValue(
-            jsonOrderLine.get("attributeValue").toString(), jsonOrderLine.getJSONObject("product")
-                .get("id").toString()));
-      }
 
       lineReferences.add(orderline);
       orderline.setLineNo((long) ((i + 1) * 10));
diff -r 25d8c134dbd4 web/org.openbravo.retail.posterminal/js/components/menu.js
--- a/web/org.openbravo.retail.posterminal/js/components/menu.js	Mon Nov 06 05:45:35 2017 +0000
+++ b/web/org.openbravo.retail.posterminal/js/components/menu.js	Fri Nov 17 14:31:41 2017 +0100
@@ -162,18 +162,27 @@
     if (this.model.get('order').get('orderType') === 3) {
       return;
     }
+
+    var errorsConvertingLayawayToReceipt = [];
+
+    if (!this.model.get('order').checkAllAttributesHasValue()) {
+      errorsConvertingLayawayToReceipt.push('OBPOS_AllAttributesNeedValue');
+    }
+
     enyo.forEach(this.model.get('order').get('payments').models, function (curPayment) {
-      receiptAllowed = false;
+      errorsConvertingLayawayToReceipt.push('OBPOS_LayawayHasPayment');
       return;
     }, this);
 
-    if (receiptAllowed) {
+    if (errorsConvertingLayawayToReceipt.length === 0) {
       this.doShowDivText({
         permission: this.permission,
         orderType: 0
       });
     } else {
-      OB.UTIL.showError(OB.I18N.getLabel('OBPOS_LayawayHasPayment'));
+      errorsConvertingLayawayToReceipt.forEach(function (error) {
+        OB.UTIL.showWarning(OB.I18N.getLabel(error));
+      });
     }
   },
   displayLogic: function () {
diff -r 25d8c134dbd4 web/org.openbravo.retail.posterminal/js/components/renderorderline.js
--- a/web/org.openbravo.retail.posterminal/js/components/renderorderline.js	Mon Nov 06 05:45:35 2017 +0000
+++ b/web/org.openbravo.retail.posterminal/js/components/renderorderline.js	Fri Nov 17 14:31:41 2017 +0100
@@ -105,10 +105,20 @@
       this.$.gross.setContent(this.model.printNet());
     }
     if (OB.MobileApp.model.hasPermission('OBPOS_EnableSupportForProductAttributes', true) && this.model.get('product').get('hasAttributes')) {
+      var attr_msg = OB.I18N.getLabel('OBPOS_AttributeValue');
+      if (this.model.get('attSetInstanceDesc')) {
+        attr_msg += this.model.get('attSetInstanceDesc');
+      } else if (this.model.get('attributeValue')) {
+        attr_msg += this.model.get('attributeValue');
+      } else {
+        attr_msg += OB.I18N.getLabel('OBPOS_AttributeValueMissing');
+      }
+
       this.createComponent({
         style: 'display: block;',
         components: [{
-          content: OB.I18N.getLabel('OBPOS_AttributeValue') + (this.model.get('attSetInstanceDesc') ? this.model.get('attSetInstanceDesc') : this.model.get('attributeValue')),
+          name: 'productAttribute',
+          content: attr_msg,
           attributes: {
             style: 'float: left; width: 100%; clear: left;'
           }
@@ -116,6 +126,10 @@
           style: 'clear: both;'
         }]
       });
+
+      if (!this.model.get('attributeValue')) {
+        this.$.productAttribute.addStyles('color: red');
+      }
     }
     if (this.model.get('product').get('characteristicDescription')) {
       this.createComponent({
@@ -472,4 +486,4 @@
   initComponents: function () {
     this.inherited(arguments);
   }
-});
\ No newline at end of file
+});
diff -r 25d8c134dbd4 web/org.openbravo.retail.posterminal/js/model/order.js
--- a/web/org.openbravo.retail.posterminal/js/model/order.js	Mon Nov 06 05:45:35 2017 +0000
+++ b/web/org.openbravo.retail.posterminal/js/model/order.js	Fri Nov 17 14:31:41 2017 +0100
@@ -1534,18 +1534,18 @@
         if (options && options.line) {
           productHavingSameAttribute = true;
         } else {
+          if (attrs && !this.checkSerialAttribute(p, attrs.attributeValue)) {
+            OB.UTIL.showConfirmation.display(OB.I18N.getLabel('OBMOBC_Error'), OB.I18N.getLabel('OBPOS_ProductDefinedAsSerialNo'));
+            if (callback) {
+              callback(false, null);
+            }
+            return;
+          }
           for (i = 0; i < lines.length; i++) {
             currentline = lines.models[i].attributes;
-            if (attrs && (currentline.attributeValue === attrs.attributeValue) && (p.id === currentline.product.id)) {
+            if (attrs && attrs.attributeValue && (currentline.attributeValue === attrs.attributeValue) && (p.id === currentline.product.id)) {
               productHavingSameAttribute = true;
               line = currentline;
-              if (p.get('isSerialNo')) {
-                OB.UTIL.showConfirmation.display(OB.I18N.getLabel('OBMOBC_Error'), OB.I18N.getLabel('OBPOS_ProductDefinedAsSerialNo'));
-                if (callback) {
-                  callback(false, null);
-                }
-                return;
-              }
             }
           }
         }
@@ -1596,7 +1596,7 @@
               line = me.get('lines').find(function (l) {
                 if (l.get('product').id === p.id && ((l.get('qty') > 0 && qty > 0) || (l.get('qty') < 0 && qty < 0))) {
                   if (attributeSearchAllowed && attrs) {
-                    if ((l.get('attributeValue') === attrs.attributeValue)) {
+                    if (attrs.attributeValue && (l.get('attributeValue') === attrs.attributeValue)) {
                       return true;
                     }
                   } else {
@@ -1744,6 +1744,38 @@
       }
     },
 
+    checkSerialAttribute: function (product, attributeValue) {
+      if (!attributeValue) {
+        return true;
+      }
+      var lines = this.get('lines');
+      var isQuotationAndAttributeAllowed = product.get('isQuotation') && OB.MobileApp.model.hasPermission('OBPOS_AskForAttributesWhenCreatingQuotation', true);
+      var i;
+      for (i = 0; i < lines.length; i++) {
+        var currentline = lines.at(i);
+        if ((currentline.get('attSetInstanceDesc') === attributeValue || currentline.get('attributeValue') === attributeValue) && (product.id === currentline.get('product').id)) {
+          if (product.get('isSerialNo')) {
+            return false;
+          }
+        }
+      }
+      return true;
+    },
+
+    checkAllAttributesHasValue: function () {
+      var lines = this.get('lines');
+      var i;
+      for (i = 0; i < lines.length; i++) {
+        var currentline = lines.at(i);
+        if (currentline.get('product').get('hasAttributes')) {
+          if (!currentline.get('attSetInstanceDesc') && !currentline.get('attributeValue')) {
+            return false;
+          }
+        }
+      }
+      return true;
+    },
+
     _loadRelatedServices: function (productType, productId, productCategory, callback, line) {
       if (productType !== 'S' && (!line || !line.get('originalOrderLineId'))) {
         if (OB.MobileApp.model.hasPermission('OBPOS_remote.product', true)) {
@@ -1974,11 +2006,15 @@
             popup: 'modalProductAttribute',
             args: {
               callback: function (attributeValue) {
-                if (attributeValue) {
+                if (!OB.UTIL.isNullOrUndefined(attributeValue)) {
                   var i;
                   if (OB.UTIL.isNullOrUndefined(attrs)) {
                     attrs = {};
                   }
+                  if (_.isEmpty(attributeValue)) {
+                    // the attributes for layaways accepts empty values, but for manage later easy to be null instead ""
+                    attributeValue = null;
+                  }
                   attrs.attributeValue = attributeValue;
                   me._addProduct(p, qty, options, attrs, function (success, orderline) {
                     if (callback) {
@@ -5566,4 +5602,4 @@
   window.OB.Model.MultiOrders = MultiOrders;
 
   window.OB.Model.modelLoaders = [];
-}());
\ No newline at end of file
+}());
diff -r 25d8c134dbd4 web/org.openbravo.retail.posterminal/js/pointofsale/view/editline.js
--- a/web/org.openbravo.retail.posterminal/js/pointofsale/view/editline.js	Mon Nov 06 05:45:35 2017 +0000
+++ b/web/org.openbravo.retail.posterminal/js/pointofsale/view/editline.js	Fri Nov 17 14:31:41 2017 +0100
@@ -500,6 +500,9 @@
             break;
           }
         }
+        if (this.$.actionButtonsContainer.$.openAttributeButton) {
+          this.$.actionButtonsContainer.$.openAttributeButton.hide();
+        }
       }
     },
     init: function (model) {
@@ -509,6 +512,10 @@
     kind: 'OB.OBPOSPointOfSale.UI.EditLine.OpenStockButton',
     name: 'checkStockButton',
     showing: false
+  }, {
+    kind: 'OB.OBPOSPointOfSale.UI.EditLine.OpenAttributeButton',
+    name: 'openAttributeButton',
+    showing: false
   }],
   published: {
     receipt: null
@@ -606,6 +613,17 @@
         } else {
           this.$.actionButtonsContainer.$.checkStockButton.hide();
         }
+        if (this.$.actionButtonsContainer.$.openAttributeButton) {
+          if (this.line) {
+            if ((this.receipt.get('isEditable') || this.receipt.get('isLayaway')) && this.line.get('product').get('hasAttributes') && OB.MobileApp.model.get('permissions').OBPOS_EnableSupportForProductAttributes) {
+              this.$.actionButtonsContainer.$.openAttributeButton.show();
+            } else {
+              this.$.actionButtonsContainer.$.openAttributeButton.hide();
+            }
+          } else {
+            this.$.actionButtonsContainer.$.openAttributeButton.hide();
+          }
+        }
       } else {
         this.$.actionButtonsContainer.$.checkStockButton.hide();
         this.$.actionButtonsContainer.$.descriptionButton.hide();
@@ -1049,4 +1067,52 @@
     this.inherited(arguments);
     this.setContent(OB.I18N.getLabel('OBPOS_checkStock'));
   }
+});
+
+enyo.kind({
+  kind: 'OB.UI.SmallButton',
+  name: 'OB.OBPOSPointOfSale.UI.EditLine.OpenAttributeButton',
+  content: '',
+  classes: 'btnlink-orange',
+  permission: 'OBPOS_EnableSupportForProductAttributes',
+  tap: function () {
+    var me = this;
+    var params = {};
+    OB.MobileApp.view.waterfall('onShowPopup', {
+      popup: 'modalProductAttribute',
+      attributeValue: this.owner.owner.line.get('attributeValue'),
+      args: {
+        callback: function (attributeValue, cancelled) {
+          var line = me.owner.owner.line;
+          if (!cancelled) {
+            if (me.owner.owner.receipt.checkSerialAttribute(line.get('product'), attributeValue)) {
+
+              if (_.isEmpty(attributeValue)) {
+                // the attributes for layaways accepts empty values, but for manage later easy to be null instead ""
+                attributeValue = null;
+              }
+
+              line.set('attributeValue', attributeValue);
+              // attributeValue is used to save the new attribute
+              // but when loading the order from backend it contains the attribute in json format
+              // and attSetInstanceDesc contains the transformed attribute into string
+              // so when we set again the attributeValue, we have to unset the attSetInstanceDesc,
+              // if not the new value in attributeValue will be ignored
+              me.owner.owner.line.unset('attSetInstanceDesc');
+            } else {
+              OB.UTIL.showConfirmation.display(OB.I18N.getLabel('OBMOBC_Error'), OB.I18N.getLabel('OBPOS_ProductDefinedAsSerialNo'));
+            }
+          }
+        },
+        options: {
+          attSetInstanceDesc: me.owner.owner.line.get('attSetInstanceDesc'),
+          attributeValue: me.owner.owner.line.get('attributeValue')
+        }
+      }
+    });
+  },
+  initComponents: function () {
+    this.inherited(arguments);
+    this.setContent(OB.I18N.getLabel('OBPOS_openAttributes'));
+  }
 });
\ No newline at end of file
diff -r 25d8c134dbd4 web/org.openbravo.retail.posterminal/js/pointofsale/view/modals/modalproductattribute.js
--- a/web/org.openbravo.retail.posterminal/js/pointofsale/view/modals/modalproductattribute.js	Mon Nov 06 05:45:35 2017 +0000
+++ b/web/org.openbravo.retail.posterminal/js/pointofsale/view/modals/modalproductattribute.js	Fri Nov 17 14:31:41 2017 +0100
@@ -26,8 +26,7 @@
       style: 'text-align: center;width: 400px; height: 40px;',
       name: 'valueAttribute',
       selectOnFocus: true,
-      isFirstFocus: true,
-      value: ''
+      isFirstFocus: true
     }]
   },
   bodyButtons: {
@@ -60,7 +59,7 @@
   saveAttribute: function (inSender, inEvent) {
     var me = this,
         inpAttributeValue = this.$.bodyContent.$.valueAttribute.getValue();
-    if ((this.validAttribute(inpAttributeValue) && inpAttributeValue)) {
+    if ((this.validAttribute(inpAttributeValue) && inpAttributeValue) || this.owner.model.get('order').get('orderType') === 2 || this.owner.model.get('order').get('isLayaway')) {
       this.args.callback(inpAttributeValue);
       this.hide();
     } else {
@@ -73,7 +72,7 @@
   },
   cancelAction: function () {
     if (this.args.callback) {
-      this.args.callback(null);
+      this.args.callback(null, true);
     }
     this.hide();
     return;
@@ -85,16 +84,18 @@
   executeOnHide: function () {
     var me = this;
     var inpAttributeValue = this.$.bodyContent.$.valueAttribute.getValue();
-    if (!inpAttributeValue && this.args.callback) {
-      this.args.callback(null);
-    }
     this.$.bodyContent.$.valueAttribute.setValue(null);
   },
   executeOnShow: function () {
+    if (this.args.options && this.args.options.attSetInstanceDesc) {
+      this.$.bodyContent.$.valueAttribute.setValue(this.args.options.attSetInstanceDesc);
+    } else if (this.args.options && this.args.options.attributeValue) {
+      this.$.bodyContent.$.valueAttribute.setValue(this.args.options.attributeValue);
+    }
     this.$.headerCloseButton.hide();
   }
 });
 OB.UI.WindowView.registerPopup('OB.OBPOSPointOfSale.UI.PointOfSale', {
   kind: 'OB.UI.ModalProductAttributes',
   name: 'OB.UI.ModalProductAttributes'
-});
\ No newline at end of file
+});
diff -r 25d8c134dbd4 web/org.openbravo.retail.posterminal/js/pointofsale/view/payment.js
--- a/web/org.openbravo.retail.posterminal/js/pointofsale/view/payment.js	Mon Nov 06 05:45:35 2017 +0000
+++ b/web/org.openbravo.retail.posterminal/js/pointofsale/view/payment.js	Fri Nov 17 14:31:41 2017 +0100
@@ -211,6 +211,10 @@
                 showing: false,
                 type: 'error'
               }, {
+                name: 'allAttributesNeedValue',
+                type: 'error',
+                showing: false
+              }, {
                 name: 'paymentMethodSelect',
                 style: 'color: orange',
                 type: 'info',
@@ -664,6 +668,7 @@
       this.$.changeexceedlimit.hide();
       this.$.overpaymentnotavailable.hide();
       this.$.overpaymentexceedlimit.hide();
+      this.$.allAttributesNeedValue.hide();
     }
     this.$.noenoughchangelbl.hide();
     this.$.onlycashpaymentmethod.hide();
@@ -712,6 +717,14 @@
     if (resultOK) {
       this.$.noenoughchangelbl.hide();
     }
+
+    // check that all attributes has value
+    if (OB.MobileApp.model.hasPermission('OBPOS_EnableSupportForProductAttributes', true) && paymentstatus.done && !this.receipt.checkAllAttributesHasValue()) {
+      this.$.donebutton.setLocalDisabled(true);
+      this.$.allAttributesNeedValue.show();
+    }
+
+
     this.alignErrorMessages();
   },
   alignErrorMessages: function () {
@@ -769,6 +782,7 @@
     errorLabelArray.push(this.$.overpaymentexceedlimit);
     errorLabelArray.push(this.$.onlycashpaymentmethod);
     errorLabelArray.push(this.$.errorMaxlimitamount);
+    errorLabelArray.push(this.$.allAttributesNeedValue);
     errorLabelArray.push(this.$.paymentMethodSelect);
     errorLabelArray.push(this.$.extrainfo);
     return errorLabelArray;
@@ -929,6 +943,7 @@
     this.$.overpaymentnotavailable.setContent(OB.I18N.getLabel('OBPOS_OverpaymentNotAvailable'));
     this.$.overpaymentexceedlimit.setContent(OB.I18N.getLabel('OBPOS_OverpaymentExcededLimit'));
     this.$.onlycashpaymentmethod.setContent(OB.I18N.getLabel('OBPOS_OnlyCashPaymentMethod'));
+    this.$.allAttributesNeedValue.setContent(OB.I18N.getLabel('OBPOS_AllAttributesNeedValue'));
   },
   init: function (model) {
     var me = this;
