From c9ea3fcac6a2ab33a32e64e71d891bb078f7c0f6 Mon Sep 17 00:00:00 2001
From: "Tiffany Chang (tic)"
Date: Wed, 7 Sep 2022 12:53:43 +0000
Subject: [PATCH] [IMP] purchase_requsition: convert custom js to OWL
For original specs, see [1].
Some performance changes: the best price/date/unit price fields are now
loaded by JS instead of passed via action context (allows for easier/
consistent reuse of view + now we can refresh without undoing any state
changes due to buttons being pushed).
[1] https://github.com/odoo/odoo/commit/f533e40f0e3f1cd34f1047b70dfdf95837d84501
closes odoo/odoo#101502
X-original-commit: 41ae508c2e6fc3c40b29b1bfc4b5dd7c4440a719
Signed-off-by: Antony Lesuisse
Signed-off-by: Tiffany Chang
---
addons/purchase_requisition/__manifest__.py | 10 ++-
.../purchase_requisition/models/purchase.py | 6 --
.../js/purchase_order_alternatives_widget.js | 52 ---------------
.../purchase_order_compare_list_renderer.js | 26 --------
...hase_order_line_compare_list_controller.js | 66 -------------------
...rchase_order_line_compare_list_renderer.js | 35 ----------
.../purchase_order_line_compare_list_view.js | 17 -----
...rchase_order_line_compare_list_renderer.js | 52 +++++++++++++++
.../purchase_order_line_compare_list_view.js | 13 ++++
.../purchase_order_alternatives_widget.js | 46 +++++++++++++
.../purchase_order_alternatives_widget.scss | 3 +
.../purchase_order_alternatives_widget.xml | 11 ++++
.../src/xml/purchase_order_line_compare.xml | 12 ----
.../tests/test_purchase_requisition.py | 8 ++-
.../views/purchase_views.xml | 4 +-
15 files changed, 136 insertions(+), 225 deletions(-)
delete mode 100644 addons/purchase_requisition/static/src/js/purchase_order_alternatives_widget.js
delete mode 100644 addons/purchase_requisition/static/src/js/purchase_order_compare_list_renderer.js
delete mode 100644 addons/purchase_requisition/static/src/js/purchase_order_line_compare_list_controller.js
delete mode 100644 addons/purchase_requisition/static/src/js/purchase_order_line_compare_list_renderer.js
delete mode 100644 addons/purchase_requisition/static/src/js/purchase_order_line_compare_list_view.js
create mode 100644 addons/purchase_requisition/static/src/views/list/purchase_order_line_compare_list_renderer.js
create mode 100644 addons/purchase_requisition/static/src/views/list/purchase_order_line_compare_list_view.js
create mode 100644 addons/purchase_requisition/static/src/widgets/purchase_order_alternatives_widget.js
create mode 100644 addons/purchase_requisition/static/src/widgets/purchase_order_alternatives_widget.scss
create mode 100644 addons/purchase_requisition/static/src/widgets/purchase_order_alternatives_widget.xml
delete mode 100644 addons/purchase_requisition/static/src/xml/purchase_order_line_compare.xml
diff --git a/addons/purchase_requisition/__manifest__.py b/addons/purchase_requisition/__manifest__.py
index 66802a19092..ce11ee6a697 100644
--- a/addons/purchase_requisition/__manifest__.py
+++ b/addons/purchase_requisition/__manifest__.py
@@ -27,12 +27,10 @@ are agreements you have with vendors to benefit from a predetermined pricing.
],
'assets': {
'web.assets_backend': [
- 'purchase_requisition/static/src/js/purchase_order_alternatives_widget.js',
- 'purchase_requisition/static/src/js/purchase_order_compare_list_renderer.js',
- 'purchase_requisition/static/src/js/purchase_order_line_compare_list_controller.js',
- 'purchase_requisition/static/src/js/purchase_order_line_compare_list_renderer.js',
- 'purchase_requisition/static/src/js/purchase_order_line_compare_list_view.js',
- 'purchase_requisition/static/src/xml/purchase_order_line_compare.xml',
+ 'purchase_requisition/static/src/*/**.js',
+ 'purchase_requisition/static/src/views/*/**.js',
+ 'purchase_requisition/static/src/*/**.scss',
+ 'purchase_requisition/static/src/*/**.xml',
],
},
'license': 'LGPL-3',
diff --git a/addons/purchase_requisition/models/purchase.py b/addons/purchase_requisition/models/purchase.py
index 5f56bb9974b..1dce4aa4dc1 100644
--- a/addons/purchase_requisition/models/purchase.py
+++ b/addons/purchase_requisition/models/purchase.py
@@ -195,15 +195,9 @@ class PurchaseOrder(models.Model):
}
def action_compare_alternative_lines(self):
- best_price_ids, best_date_ids, best_price_unit_ids = self.get_tender_best_lines()
ctx = dict(
self.env.context,
search_default_groupby_product=True,
- params={
- 'best_price_ids': best_price_ids,
- 'best_date_ids': best_date_ids,
- 'best_price_unit_ids': best_price_unit_ids,
- },
)
view_id = self.env.ref('purchase_requisition.purchase_order_line_compare_tree').id
return {
diff --git a/addons/purchase_requisition/static/src/js/purchase_order_alternatives_widget.js b/addons/purchase_requisition/static/src/js/purchase_order_alternatives_widget.js
deleted file mode 100644
index 33aceb34d1a..00000000000
--- a/addons/purchase_requisition/static/src/js/purchase_order_alternatives_widget.js
+++ /dev/null
@@ -1,52 +0,0 @@
-/** @odoo-module **/
-
-import field_registry from 'web.field_registry';
-import { FieldMany2Many } from 'web.relational_fields';
-import PurchaseOrderCompareListRenderer from '@purchase_requisition/js/purchase_order_compare_list_renderer';
-
-const FieldMany2ManySameWindow = FieldMany2Many.extend({
-
- /**
- * @override
- */
- init: function (parent, name, record, options) {
- this._super(...arguments);
- this.isMany2Many = true;
- },
-
- /**
- * Override to ensure we can't unlink a PO from itself (i.e. confusing behavior)
- * @override
- */
- _getRenderer: function () {
- if (this.view.arch.tag === 'tree') {
- return PurchaseOrderCompareListRenderer;
- }
- return this._super(...arguments);
- },
-
- /**
- * Override to open record in same window w/breadcrumb extended
- * @override
- */
- _onOpenRecord: function (ev) {
- ev.stopPropagation();
- const targetId = ev.target.state.data.find(obj => {
- return obj.id === ev.data.id;
- }).res_id;
- // don't re-open current record
- if (targetId !== this.record.res_id) {
- this._rpc({
- model: this.model,
- method: 'get_formview_action',
- args: [[targetId]],
- context: this.record.getContext(this.recordParams),
- domain: this.record.getDomain(this.recordParams),
- }).then(action => {
- this.trigger_up('do_action', {action: action});
- });
- }
- }
-});
-
-field_registry.add('many2many_same_window', FieldMany2ManySameWindow);
diff --git a/addons/purchase_requisition/static/src/js/purchase_order_compare_list_renderer.js b/addons/purchase_requisition/static/src/js/purchase_order_compare_list_renderer.js
deleted file mode 100644
index cb345c9b48e..00000000000
--- a/addons/purchase_requisition/static/src/js/purchase_order_compare_list_renderer.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/** @odoo-module **/
-
-import ListRenderer from 'web.ListRenderer';
-
-
-const PurchaseOrderCompareListRenderer = ListRenderer.extend({
- init: function (parent, state, params) {
- this._super(...arguments);
- this.active_id = parent.res_id;
- },
-
- /**
- * @override
- * @private
- * @returns {Promise}
- */
- _renderRow: function (record) {
- const $tr = this._super(...arguments);
- if (record.res_id === this.active_id && $tr.find('.o_list_record_remove').length) {
- $tr.find(".o_list_record_remove").remove();
- }
- return $tr;
- }
-});
-
-export default PurchaseOrderCompareListRenderer;
diff --git a/addons/purchase_requisition/static/src/js/purchase_order_line_compare_list_controller.js b/addons/purchase_requisition/static/src/js/purchase_order_line_compare_list_controller.js
deleted file mode 100644
index c197299c271..00000000000
--- a/addons/purchase_requisition/static/src/js/purchase_order_line_compare_list_controller.js
+++ /dev/null
@@ -1,66 +0,0 @@
-/** @odoo-module **/
-
-import ListController from 'web.ListController';
-
-const PurchaseOrderLineCompareListController = ListController.extend({
-
- // -------------------------------------------------------------------------
- // Public
- // -------------------------------------------------------------------------
-
- init: function (parent, model, renderer, params) {
- this.context = renderer.state.getContext();
- this.best_date_ids = this.context.params.best_date_ids;
- this.best_price_ids = this.context.params.best_price_ids;
- this.best_price_unit_ids = this.context.params.best_price_unit_ids;
- return this._super(...arguments);
- },
-
- // -------------------------------------------------------------------------
- // Handlers
- // -------------------------------------------------------------------------
- /**
- * @override
- */
- _onButtonClicked: function (ev) {
- if (ev.data.attrs.class && ev.data.attrs.class.split(' ').includes('o_clear_qty_buttons')) {
- ev.stopPropagation();
- var self = this;
- return this._callButtonAction(ev.data.attrs, ev.data.record).then(() => {
- const context = this.model.localData[0] && this.model.localData[0].getContext() || {};
- return self._rpc({
- model: "purchase.order",
- method: 'get_tender_best_lines',
- args: [self.context.active_id],
- context: context,
- }).then((best_lines) => {
- self.renderer.best_date_ids = best_lines[0] || [];
- self.renderer.best_price_ids = best_lines[1] || [];
- self.renderer.best_price_unit_ids = best_lines[2] || [];
- self.reload();
- });
- });
- } else {
- this._super.apply(this, arguments);
- }
- },
-
- _onHeaderButtonClicked: async function (node) {
- await this._super(...arguments);
- if (node.attrs.name && node.attrs.name === 'action_clear_quantities') {
- const context = this.model.localData[0] && this.model.localData[0].getContext() || {};
- const best_lines = await this._rpc({
- model: 'purchase.order',
- method: 'get_tender_best_lines',
- args: this.context.active_ids,
- context,
- });
- this.renderer.best_date_ids = best_lines[0];
- this.renderer.best_price_ids = best_lines[1];
- this.renderer.best_price_unit_ids = best_lines[2];
- this.reload();
- }
- },
-});
-
-export default PurchaseOrderLineCompareListController;
diff --git a/addons/purchase_requisition/static/src/js/purchase_order_line_compare_list_renderer.js b/addons/purchase_requisition/static/src/js/purchase_order_line_compare_list_renderer.js
deleted file mode 100644
index 9bf90ea4dc3..00000000000
--- a/addons/purchase_requisition/static/src/js/purchase_order_line_compare_list_renderer.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/** @odoo-module **/
-
-import ListRenderer from 'web.ListRenderer';
-
-
-const PurchaseOrderLineCompareListRenderer = ListRenderer.extend({
-
- init: function (parent, state, params) {
- this._super(...arguments);
- this.best_date_ids = this.state.context.params.best_date_ids;
- this.best_price_ids = this.state.context.params.best_price_ids;
- this.best_price_unit_ids = this.state.context.params.best_price_unit_ids;
- },
-
- /**
- * @override
- * @private
- * @returns {Promise}
- */
- _renderRow: function (record) {
- const $tr = this._super(...arguments);
- if (this.best_date_ids.includes(record.res_id)) {
- $tr.find('[name="date_planned"]').toggleClass('text-success');
- }
- if (this.best_price_ids.includes(record.res_id)) {
- $tr.find('[name="price_subtotal"]').toggleClass('text-success');
- }
- if (this.best_price_unit_ids.includes(record.res_id)) {
- $tr.find('[name="price_unit"]').toggleClass('text-success');
- }
- return $tr;
- }
-});
-
-export default PurchaseOrderLineCompareListRenderer;
diff --git a/addons/purchase_requisition/static/src/js/purchase_order_line_compare_list_view.js b/addons/purchase_requisition/static/src/js/purchase_order_line_compare_list_view.js
deleted file mode 100644
index 96782055cde..00000000000
--- a/addons/purchase_requisition/static/src/js/purchase_order_line_compare_list_view.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/** @odoo-module **/
-
-import ListView from 'web.ListView';
-import PurchaseOrderLineCompareListController from '@purchase_requisition/js/purchase_order_line_compare_list_controller';
-import PurchaseOrderLineCompareListRenderer from '@purchase_requisition/js/purchase_order_line_compare_list_renderer';
-import viewRegistry from 'web.view_registry';
-
-const PurchaseOrderLineCompareListView = ListView.extend({
- config: Object.assign({}, ListView.prototype.config, {
- Controller: PurchaseOrderLineCompareListController,
- Renderer: PurchaseOrderLineCompareListRenderer,
- }),
-});
-
-viewRegistry.add('purchase_order_line_compare', PurchaseOrderLineCompareListView);
-
-export default PurchaseOrderLineCompareListView;
diff --git a/addons/purchase_requisition/static/src/views/list/purchase_order_line_compare_list_renderer.js b/addons/purchase_requisition/static/src/views/list/purchase_order_line_compare_list_renderer.js
new file mode 100644
index 00000000000..e5b26831ca6
--- /dev/null
+++ b/addons/purchase_requisition/static/src/views/list/purchase_order_line_compare_list_renderer.js
@@ -0,0 +1,52 @@
+/** @odoo-module */
+
+import { ListRenderer } from "@web/views/list/list_renderer";
+
+const { onWillStart, useState, useSubEnv } = owl;
+
+export class PurchaseOrderLineCompareListRenderer extends ListRenderer {
+ setup() {
+ super.setup();
+ this.bestFields = useState({
+ best_price_ids: [],
+ best_date_ids: [],
+ best_price_unit_ids: [],
+ });
+ onWillStart(async () => {
+ await this.updateBestFields();
+ });
+ const defaultOnClickViewButton = this.env.onClickViewButton;
+ useSubEnv({
+ onClickViewButton: async (params) => {
+ await defaultOnClickViewButton(params);
+ await this.updateBestFields();
+ }
+ });
+ }
+
+ async updateBestFields() {
+ [this.bestFields.best_price_ids,
+ this.bestFields.best_date_ids,
+ this.bestFields.best_price_unit_ids] = await this.props.list.model.orm.call(
+ "purchase.order",
+ "get_tender_best_lines",
+ [this.props.list.context.active_id],
+ { context: this.props.list.context }
+ );
+ }
+
+ getCellClass(column, record) {
+ let classNames = super.getCellClass(...arguments);
+ const customClassNames = [];
+ if (column.name === "price_subtotal" && this.bestFields.best_price_ids.includes(record.resId)) {
+ customClassNames.push("text-success");
+ }
+ if (column.name === "date_planned" && this.bestFields.best_date_ids.includes(record.resId)) {
+ customClassNames.push("text-success");
+ }
+ if (column.name === "price_unit" && this.bestFields.best_price_unit_ids.includes(record.resId)) {
+ customClassNames.push("text-success");
+ }
+ return classNames.concat(" ", customClassNames.join(" "));
+ }
+}
diff --git a/addons/purchase_requisition/static/src/views/list/purchase_order_line_compare_list_view.js b/addons/purchase_requisition/static/src/views/list/purchase_order_line_compare_list_view.js
new file mode 100644
index 00000000000..72a8d9ceece
--- /dev/null
+++ b/addons/purchase_requisition/static/src/views/list/purchase_order_line_compare_list_view.js
@@ -0,0 +1,13 @@
+/** @odoo-module **/
+
+import { listView } from '@web/views/list/list_view';
+import { registry } from "@web/core/registry";
+import { PurchaseOrderLineCompareListRenderer } from "./purchase_order_line_compare_list_renderer";
+
+
+export const PurchaseOrderLineCompareListView = {
+ ...listView,
+ Renderer: PurchaseOrderLineCompareListRenderer,
+};
+
+registry.category("views").add("purchase_order_line_compare", PurchaseOrderLineCompareListView);
diff --git a/addons/purchase_requisition/static/src/widgets/purchase_order_alternatives_widget.js b/addons/purchase_requisition/static/src/widgets/purchase_order_alternatives_widget.js
new file mode 100644
index 00000000000..4ada4a25f4a
--- /dev/null
+++ b/addons/purchase_requisition/static/src/widgets/purchase_order_alternatives_widget.js
@@ -0,0 +1,46 @@
+/** @odoo-module */
+
+import { registry } from "@web/core/registry";
+import { useService } from "@web/core/utils/hooks";
+import { X2ManyField } from "@web/views/fields/x2many/x2many_field";
+import { ListRenderer } from "@web/views/list/list_renderer";
+
+
+export class FieldMany2ManyAltPOsRenderer extends ListRenderer {
+ isCurrentRecord(record) {
+ return record.data.id === this.env.model.root.data.id;
+ }
+}
+
+FieldMany2ManyAltPOsRenderer.recordRowTemplate = "purchase_requisition.AltPOsListRenderer.RecordRow";
+
+export class FieldMany2ManyAltPOs extends X2ManyField {
+ setup() {
+ this.orm = useService("orm");
+ this.action = useService("action");
+ // TODO: this is a terrible hack, make this a proper extension of many2many if/when possible
+ this.props.record.activeFields[this.props.name].widget = "many2many";
+ super.setup();
+ }
+
+ /**
+ * Override to: avoid reopening currently open record
+ * open record in same window w/breadcrumb extended
+ * @override
+ */
+ async openRecord(record) {
+ if (record.data.id !== this.props.record.data.id) {
+ const action = await this.orm.call(record.resModel, "get_formview_action", [[record.data.id]], {
+ context: this.props.context,
+ });
+ await this.action.doAction(action);
+ }
+ }
+}
+
+FieldMany2ManyAltPOs.components = {
+ ...X2ManyField.components,
+ ListRenderer: FieldMany2ManyAltPOsRenderer,
+};
+
+registry.category("fields").add("many2many_alt_pos", FieldMany2ManyAltPOs);
diff --git a/addons/purchase_requisition/static/src/widgets/purchase_order_alternatives_widget.scss b/addons/purchase_requisition/static/src/widgets/purchase_order_alternatives_widget.scss
new file mode 100644
index 00000000000..59d1a1468eb
--- /dev/null
+++ b/addons/purchase_requisition/static/src/widgets/purchase_order_alternatives_widget.scss
@@ -0,0 +1,3 @@
+.o_field_many2many_alt_pos {
+ width: 100%;
+}
diff --git a/addons/purchase_requisition/static/src/widgets/purchase_order_alternatives_widget.xml b/addons/purchase_requisition/static/src/widgets/purchase_order_alternatives_widget.xml
new file mode 100644
index 00000000000..3d3f524f3e4
--- /dev/null
+++ b/addons/purchase_requisition/static/src/widgets/purchase_order_alternatives_widget.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+ activeActions and !isCurrentRecord(record)
+
+
+
+
diff --git a/addons/purchase_requisition/static/src/xml/purchase_order_line_compare.xml b/addons/purchase_requisition/static/src/xml/purchase_order_line_compare.xml
deleted file mode 100644
index 58c2de1d7f1..00000000000
--- a/addons/purchase_requisition/static/src/xml/purchase_order_line_compare.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/addons/purchase_requisition/tests/test_purchase_requisition.py b/addons/purchase_requisition/tests/test_purchase_requisition.py
index 8f13844fce9..03f23ecc25c 100644
--- a/addons/purchase_requisition/tests/test_purchase_requisition.py
+++ b/addons/purchase_requisition/tests/test_purchase_requisition.py
@@ -150,11 +150,13 @@ class TestPurchaseRequisition(TestPurchaseRequisitionCommon):
alt_po_1.order_line.date_planned += timedelta(days=1)
alt_po_1.order_line.price_unit = unit_price - 10
action = orig_po.action_compare_alternative_lines()
- params = action['context']['params']
- best_price_pol = self.env['purchase.order.line'].browse(params['best_price_ids'])
- best_date_pol = self.env['purchase.order.line'].browse(params['best_date_ids'])
+ best_price_ids, best_date_ids, best_price_unit_ids = orig_po.get_tender_best_lines()
+ best_price_pol = self.env['purchase.order.line'].browse(best_price_ids)
+ best_date_pol = self.env['purchase.order.line'].browse(best_date_ids)
+ best_unit_price_pol = self.env['purchase.order.line'].browse(best_price_unit_ids)
self.assertEqual(best_price_pol.order_id.id, alt_po_1.id, "Best price PO line was not correctly calculated")
self.assertEqual(best_date_pol.order_id.id, orig_po.id, "Best date PO line was not correctly calculated")
+ self.assertEqual(best_unit_price_pol.order_id.id, alt_po_1.id, "Best unit price PO line was not correctly calculated")
# second flow: create extra alt PO, check that all 3 POs are correctly auto-linked
action = orig_po.action_create_alternative()
diff --git a/addons/purchase_requisition/views/purchase_views.xml b/addons/purchase_requisition/views/purchase_views.xml
index a8b67a4c63b..c899268c1bc 100644
--- a/addons/purchase_requisition/views/purchase_views.xml
+++ b/addons/purchase_requisition/views/purchase_views.xml
@@ -28,8 +28,8 @@
-
-
+
+