diff --git a/addons/sale/static/src/js/product_discount_widget.js b/addons/sale/static/src/js/product_discount_widget.js
new file mode 100644
index 00000000000..ede118000c0
--- /dev/null
+++ b/addons/sale/static/src/js/product_discount_widget.js
@@ -0,0 +1,37 @@
+odoo.define('sale.product_discount', function (require) {
+ "use strict";
+
+ const BasicFields = require('web.basic_fields');
+ const FieldsRegistry = require('web.field_registry');
+
+ /**
+ * The sale.product_discount widget is a simple widget extending FieldFloat
+ *
+ *
+ * !!! WARNING !!!
+ *
+ * This widget is only designed for sale_order_line creation/updates.
+ * !!! It should only be used on a discount field !!!
+ */
+ const ProductDiscountWidget = BasicFields.FieldFloat.extend({
+
+ /**
+ * Override changes at a discount.
+ *
+ * @override
+ * @param {OdooEvent} ev
+ *
+ */
+ async reset(record, ev) {
+ if (ev && ev.data.changes && ev.data.changes.discount >= 0) {
+ this.trigger_up('open_discount_wizard');
+ }
+ this._super(...arguments);
+ },
+ });
+
+ FieldsRegistry.add('product_discount', ProductDiscountWidget);
+
+ return ProductDiscountWidget;
+
+});
diff --git a/addons/sale/static/src/js/sale_order_view.js b/addons/sale/static/src/js/sale_order_view.js
new file mode 100644
index 00000000000..6956f277e16
--- /dev/null
+++ b/addons/sale/static/src/js/sale_order_view.js
@@ -0,0 +1,56 @@
+odoo.define('sale.SaleOrderView', function (require) {
+ "use strict";
+
+ const FormController = require('web.FormController');
+ const FormView = require('web.FormView');
+ const viewRegistry = require('web.view_registry');
+ const Dialog = require('web.Dialog');
+ const core = require('web.core');
+ const _t = core._t;
+
+ const SaleOrderFormController = FormController.extend({
+ custom_events: _.extend({}, FormController.prototype.custom_events, {
+ open_discount_wizard: '_onOpenDiscountWizard',
+ }),
+
+ // -------------------------------------------------------------------------
+ // Handlers
+ // -------------------------------------------------------------------------
+
+ /**
+ * Handler called if user changes the discount field in the sale order line.
+ * The wizard will open only if
+ * (1) Sale order line is 3 or more
+ * (2) First sale order line is changed to discount
+ * (3) Discount is the same in all sale order line
+ */
+ _onOpenDiscountWizard(ev) {
+ const orderLines = this.renderer.state.data.order_line.data;
+ const recordData = ev.target.recordData;
+ const isEqualDiscount = orderLines.slice(1).every(line => line.data.discount === recordData.discount);
+ if (orderLines.length >= 3 && recordData.sequence === orderLines[0].data.sequence && isEqualDiscount) {
+ Dialog.confirm(this, _t("Do you want to apply this discount to all order lines?"), {
+ confirm_callback: () => {
+ orderLines.slice(1).forEach((line) => {
+ this.trigger_up('field_changed', {
+ dataPointID: this.renderer.state.id,
+ changes: {order_line: {operation: "UPDATE", id: line.id, data: {discount: orderLines[0].data.discount}}},
+ });
+ });
+ },
+ });
+ }
+ },
+ });
+
+ const SaleOrderView = FormView.extend({
+ config: _.extend({}, FormView.prototype.config, {
+ Controller: SaleOrderFormController,
+ }),
+ });
+
+ viewRegistry.add('sale_discount_form', SaleOrderView);
+
+ return SaleOrderView;
+
+});
diff --git a/addons/sale/views/assets.xml b/addons/sale/views/assets.xml
index cc7b45a960f..2b78d5cc411 100644
--- a/addons/sale/views/assets.xml
+++ b/addons/sale/views/assets.xml
@@ -9,6 +9,8 @@
+
+
diff --git a/addons/sale/views/sale_views.xml b/addons/sale/views/sale_views.xml
index 0d7a0bb1005..3c6bc7ce015 100644
--- a/addons/sale/views/sale_views.xml
+++ b/addons/sale/views/sale_views.xml
@@ -259,7 +259,7 @@
sale.order.form
sale.order
-