From 98e0d559ba17c64a54adbbbe68d752ae29fcbdcb Mon Sep 17 00:00:00 2001 From: Enric Tobella Date: Thu, 8 Feb 2024 08:31:03 +0100 Subject: [PATCH] [MIG] account_reconcile_oca: Finish migration --- account_reconcile_oca/__manifest__.py | 1 + .../models/account_bank_statement_line.py | 45 ++++++++---- .../models/account_journal.py | 5 +- .../models/account_reconcile_abstract.py | 6 +- .../js/reconcile/reconcile_controller.esm.js | 9 ++- .../js/widgets/reconcile_chatter_field.esm.js | 19 ++++-- .../js/widgets/reconcile_data_widget.esm.js | 22 +++--- .../widgets/reconcile_move_line_widget.esm.js | 68 +++++++++++++++++-- .../js/widgets/selection_badge_uncheck.esm.js | 11 ++- .../static/src/xml/reconcile.xml | 6 +- .../tests/test_account_reconcile.py | 24 ++++--- .../tests/test_bank_account_reconcile.py | 15 ++-- .../views/account_bank_statement_line.xml | 18 ++--- .../views/account_move_line.xml | 7 +- 14 files changed, 190 insertions(+), 66 deletions(-) diff --git a/account_reconcile_oca/__manifest__.py b/account_reconcile_oca/__manifest__.py index 44a4e7f9..49c467be 100644 --- a/account_reconcile_oca/__manifest__.py +++ b/account_reconcile_oca/__manifest__.py @@ -12,6 +12,7 @@ "website": "https://github.com/OCA/account-reconcile", "depends": [ "account_statement_base", + "account_reconcile_model_oca", "base_sparse_field", ], "data": [ diff --git a/account_reconcile_oca/models/account_bank_statement_line.py b/account_reconcile_oca/models/account_bank_statement_line.py index 201b680e..f0ff494f 100644 --- a/account_reconcile_oca/models/account_bank_statement_line.py +++ b/account_reconcile_oca/models/account_bank_statement_line.py @@ -3,7 +3,7 @@ from collections import defaultdict -from odoo import Command, _, api, fields, models +from odoo import Command, _, api, fields, models, tools from odoo.exceptions import UserError from odoo.tools import float_is_zero @@ -186,10 +186,14 @@ class AccountBankStatementLine(models.Model): suspense_line = { "reference": "reconcile_auxiliary;%s" % reconcile_auxiliary_id, "id": False, - "account_id": self.journal_id.suspense_account_id.display_name, + "account_id": [ + self.journal_id.suspense_account_id.id, + self.journal_id.suspense_account_id.display_name, + ], "partner_id": self.partner_id - and self.partner_id.display_name - or (False, self.partner_name), + and [self.partner_id.id, self.partner_id.display_name] + or (self.partner_name and (False, self.partner_name)) + or False, "date": fields.Date.to_string(self.date), "name": self.payment_ref or self.name, "amount": -total_amount, @@ -289,9 +293,16 @@ class AccountBankStatementLine(models.Model): { "name": self.manual_name, "partner_id": self.manual_partner_id - and self.manual_partner_id.display_name - or (False, self.partner_name), - "account_id": self.manual_account_id.display_name + and [ + self.manual_partner_id.id, + self.manual_partner_id.display_name, + ] + or (self.partner_name and (False, self.partner_name)) + or False, + "account_id": [ + self.manual_account_id.id, + self.manual_account_id.display_name, + ] if self.manual_account_id else [False, _("Undefined")], "amount": self.manual_amount, @@ -374,9 +385,12 @@ class AccountBankStatementLine(models.Model): "debit": amount if amount > 0 else 0, "credit": -amount if amount < 0 else 0, "kind": "other", - "account_id": self.env["account.account"] - .browse(line["account_id"]) - .display_name, + "account_id": [ + line["account_id"], + self.env["account.account"] + .browse(line["account_id"]) + .display_name, + ], "date": fields.Date.to_string(self.date), "line_currency_id": self.company_id.currency_id.id, "currency_id": self.company_id.currency_id.id, @@ -386,7 +400,8 @@ class AccountBankStatementLine(models.Model): reconcile_auxiliary_id += 1 if line.get("partner_id"): new_line["partner_id"] = ( - self.env["res.partner"].browse(line["partner_id"]).display_name + line["partner_id"], + self.env["res.partner"].browse(line["partner_id"]).display_name, ) new_data.append(new_line) return new_data, reconcile_auxiliary_id @@ -409,7 +424,7 @@ class AccountBankStatementLine(models.Model): { "reference": "reconcile_auxiliary;%s" % reconcile_auxiliary_id, "id": False, - "account_id": account.display_name, + "account_id": [account.id, account.display_name], "partner_id": False, "date": fields.Date.to_string(self.date), "name": self.payment_ref or self.name, @@ -620,6 +635,10 @@ class AccountBankStatementLine(models.Model): @api.model_create_multi def create(self, mvals): result = super().create(mvals) + if tools.config["test_enable"] and not self.env.context.get( + "_test_account_reconcile_oca" + ): + return result models = self.env["account.reconcile.model"].search( [ ("rule_type", "in", ["invoice_matching", "writeoff_suggestion"]), @@ -726,6 +745,6 @@ class AccountBankStatementLine(models.Model): max_amount=max_amount, from_unreconcile=from_unreconcile, ) - if vals["partner_id"] is False: + if vals["partner_id"] is False and self.partner_name: vals["partner_id"] = (False, self.partner_name) return vals diff --git a/account_reconcile_oca/models/account_journal.py b/account_reconcile_oca/models/account_journal.py index 613ab41a..8c6409c5 100644 --- a/account_reconcile_oca/models/account_journal.py +++ b/account_reconcile_oca/models/account_journal.py @@ -15,6 +15,9 @@ class AccountJournal(models.Model): def get_rainbowman_message(self): self.ensure_one() - if self.get_journal_dashboard_datas()["number_to_reconcile"] > 0: + if ( + self._get_journal_dashboard_data_batched()[self.id]["number_to_reconcile"] + > 0 + ): return False return _("Well done! Everything has been reconciled") diff --git a/account_reconcile_oca/models/account_reconcile_abstract.py b/account_reconcile_oca/models/account_reconcile_abstract.py index d5a83f06..edb9c427 100644 --- a/account_reconcile_oca/models/account_reconcile_abstract.py +++ b/account_reconcile_oca/models/account_reconcile_abstract.py @@ -68,8 +68,10 @@ class AccountReconcileAbstract(models.AbstractModel): vals = { "reference": "account.move.line;%s" % line.id, "id": line.id, - "account_id": line.account_id.display_name, - "partner_id": line.partner_id and line.partner_id.display_name or False, + "account_id": [line.account_id.id, line.account_id.display_name], + "partner_id": [line.partner_id.id, line.partner_id.display_name] + if line.partner_id + else False, "date": fields.Date.to_string(line.date), "name": line.name, "debit": amount if amount > 0 else 0.0, diff --git a/account_reconcile_oca/static/src/js/reconcile/reconcile_controller.esm.js b/account_reconcile_oca/static/src/js/reconcile/reconcile_controller.esm.js index 801f233f..cf80ed8f 100644 --- a/account_reconcile_oca/static/src/js/reconcile/reconcile_controller.esm.js +++ b/account_reconcile_oca/static/src/js/reconcile/reconcile_controller.esm.js @@ -1,8 +1,8 @@ /** @odoo-module */ const {useState, useSubEnv} = owl; +import {useBus, useService} from "@web/core/utils/hooks"; import {KanbanController} from "@web/views/kanban/kanban_controller"; import {View} from "@web/views/view"; -import {useService} from "@web/core/utils/hooks"; export class ReconcileController extends KanbanController { async setup() { @@ -19,7 +19,9 @@ export class ReconcileController extends KanbanController { this.action = useService("action"); this.router = useService("router"); this.activeActions = this.props.archInfo.activeActions; - this.model.addEventListener("update", () => this.selectRecord(), {once: true}); + useBus(this.model.bus, "update", () => { + this.selectRecord(); + }); } exposeController(controller) { this.form_controller = controller; @@ -55,7 +57,7 @@ export class ReconcileController extends KanbanController { }; } async selectRecord(record) { - var resId = undefined; + var resId = false; if (record === undefined && this.props.resId) { resId = this.props.resId; } else if (record === undefined) { @@ -97,6 +99,7 @@ export class ReconcileController extends KanbanController { this.router.pushState({id: resId}); } } + ReconcileController.components = { ...ReconcileController.components, View, diff --git a/account_reconcile_oca/static/src/js/widgets/reconcile_chatter_field.esm.js b/account_reconcile_oca/static/src/js/widgets/reconcile_chatter_field.esm.js index 2e481485..72a045a4 100644 --- a/account_reconcile_oca/static/src/js/widgets/reconcile_chatter_field.esm.js +++ b/account_reconcile_oca/static/src/js/widgets/reconcile_chatter_field.esm.js @@ -3,14 +3,25 @@ // import {ChatterContainer} from "@mail/components/chatter_container/chatter_container"; // import {Chatter} from "@mail/core/web/chatter"; import {registry} from "@web/core/registry"; +import {standardFieldProps} from "@web/views/fields/standard_field_props"; +import {Chatter} from "@mail/core/web/chatter"; const {Component} = owl; -export class AccountReconcileChatterWidget extends Component {} +export class AccountReconcileChatterWidget extends Component { + setup() { + super.setup(); + console.log(this); + } +} +AccountReconcileChatterWidget.props = {...standardFieldProps}; AccountReconcileChatterWidget.template = "account_reconcile_oca.AccountReconcileChatterWidget"; -// AccountReconcileChatterWidget.components = {...Component.components, ChatterContainer}; - +AccountReconcileChatterWidget.components = {...Component.components, Chatter}; +export const AccountReconcileChatterWidgetField = { + component: AccountReconcileChatterWidget, + supportedTypes: [], +}; registry .category("fields") - .add("account_reconcile_oca_chatter", AccountReconcileChatterWidget); + .add("account_reconcile_oca_chatter", AccountReconcileChatterWidgetField); diff --git a/account_reconcile_oca/static/src/js/widgets/reconcile_data_widget.esm.js b/account_reconcile_oca/static/src/js/widgets/reconcile_data_widget.esm.js index 932b3911..3deb8499 100644 --- a/account_reconcile_oca/static/src/js/widgets/reconcile_data_widget.esm.js +++ b/account_reconcile_oca/static/src/js/widgets/reconcile_data_widget.esm.js @@ -1,9 +1,7 @@ /** @odoo-module **/ - -import {formatDate, formatMonetary} from "@web/views/fields/formatters"; -import {parseDate} from "@web/core/l10n/dates"; +import {formatDate, parseDate} from "@web/core/l10n/dates"; +import {formatMonetary} from "@web/views/fields/formatters"; import {registry} from "@web/core/registry"; -import {session} from "@web/session"; const {Component} = owl; @@ -24,19 +22,19 @@ export class AccountReconcileDataWidget extends Component { var data = this.props.record.data[this.props.name].data; for (var line in data) { data[line].amount_format = formatMonetary(data[line].amount, undefined, { - currency: session.get_currency(data[line].currency_id), + currency: data[line].currency_id, }); data[line].debit_format = formatMonetary(data[line].debit, undefined, { - currency: session.get_currency(data[line].currency_id), + currency: data[line].currency_id, }); data[line].credit_format = formatMonetary(data[line].credit, undefined, { - currency: session.get_currency(data[line].currency_id), + currency: data[line].currency_id, }); data[line].amount_currency_format = formatMonetary( data[line].currency_amount, undefined, { - currency: session.get_currency(data[line].line_currency_id), + currency: data[line].line_currency_id, } ); if (data[line].original_amount) { @@ -44,7 +42,7 @@ export class AccountReconcileDataWidget extends Component { data[line].original_amount, undefined, { - currency: session.get_currency(data[line].currency_id), + currency: data[line].currency_id, } ); } @@ -75,6 +73,10 @@ export class AccountReconcileDataWidget extends Component { } AccountReconcileDataWidget.template = "account_reconcile_oca.ReconcileDataWidget"; +export const AccountReconcileDataWidgetField = { + component: AccountReconcileDataWidget, + supportedTypes: [], +}; registry .category("fields") - .add("account_reconcile_oca_data", AccountReconcileDataWidget); + .add("account_reconcile_oca_data", AccountReconcileDataWidgetField); diff --git a/account_reconcile_oca/static/src/js/widgets/reconcile_move_line_widget.esm.js b/account_reconcile_oca/static/src/js/widgets/reconcile_move_line_widget.esm.js index a539bca4..05a62076 100644 --- a/account_reconcile_oca/static/src/js/widgets/reconcile_move_line_widget.esm.js +++ b/account_reconcile_oca/static/src/js/widgets/reconcile_move_line_widget.esm.js @@ -1,19 +1,29 @@ /** @odoo-module **/ import {View} from "@web/views/view"; +import {evaluateBooleanExpr} from "@web/core/py_js/py"; +import {getFieldContext} from "@web/model/relational_model/utils"; import {registry} from "@web/core/registry"; +import {standardFieldProps} from "@web/views/fields/standard_field_props"; const {Component, useSubEnv} = owl; export class AccountReconcileMatchWidget extends Component { setup() { // Necessary in order to avoid a loop - super.setup(...arguments); useSubEnv({ config: {}, parentController: this.env.parentController, }); } + + getDomain() { + let domain = this.props.domain; + if (typeof domain === "function") { + domain = domain(); + } + return domain; + } get listViewProperties() { return { type: "list", @@ -22,15 +32,18 @@ export class AccountReconcileMatchWidget extends Component { // Hiding the control panel buttons "top-left": false, "bottom-left": false, + layoutActions: false, }, }, + noBreadcrumbs: true, resModel: this.props.record.fields[this.props.name].relation, searchMenuTypes: ["filter"], - domain: this.props.record.getFieldDomain(this.props.name).toList(), + domain: this.getDomain(), context: { - ...this.props.record.getFieldContext(this.props.name), + ...this.props.context, + ...getFieldContext(this.props.record, this.props.name), }, - // Disables de selector + // Disables selector allowSelectors: false, // We need to force the search view in order to show the right one searchViewId: false, @@ -39,13 +52,56 @@ export class AccountReconcileMatchWidget extends Component { }; } } +AccountReconcileMatchWidget.props = { + ...standardFieldProps, + placeholder: {type: String, optional: true}, + canOpen: {type: Boolean, optional: true}, + canCreate: {type: Boolean, optional: true}, + canWrite: {type: Boolean, optional: true}, + canQuickCreate: {type: Boolean, optional: true}, + canCreateEdit: {type: Boolean, optional: true}, + context: {type: String, optional: true}, + domain: {type: [Array, Function], optional: true}, + nameCreateField: {type: String, optional: true}, + searchLimit: {type: Number, optional: true}, + relation: {type: String, optional: true}, + string: {type: String, optional: true}, + canScanBarcode: {type: Boolean, optional: true}, + update: {type: Function, optional: true}, + value: {optional: true}, + decorations: {type: Object, optional: true}, +}; AccountReconcileMatchWidget.template = "account_reconcile_oca.ReconcileMatchWidget"; - AccountReconcileMatchWidget.components = { ...AccountReconcileMatchWidget.components, View, }; +export const AccountReconcileMatchWidgetField = { + component: AccountReconcileMatchWidget, + supportedTypes: [], + extractProps({attrs, context, decorations, options}, dynamicInfo) { + const hasCreatePermission = attrs.can_create + ? evaluateBooleanExpr(attrs.can_create) + : true; + const hasWritePermission = attrs.can_write + ? evaluateBooleanExpr(attrs.can_write) + : true; + const canCreate = options.no_create ? false : hasCreatePermission; + return { + placeholder: attrs.placeholder, + canOpen: !options.no_open, + canCreate, + canWrite: hasWritePermission, + canQuickCreate: canCreate && !options.no_quick_create, + canCreateEdit: canCreate && !options.no_create_edit, + context: context, + decorations, + domain: dynamicInfo.domain, + }; + }, +}; + registry .category("fields") - .add("account_reconcile_oca_match", AccountReconcileMatchWidget); + .add("account_reconcile_oca_match", AccountReconcileMatchWidgetField); diff --git a/account_reconcile_oca/static/src/js/widgets/selection_badge_uncheck.esm.js b/account_reconcile_oca/static/src/js/widgets/selection_badge_uncheck.esm.js index 8d238cc6..4f27409b 100644 --- a/account_reconcile_oca/static/src/js/widgets/selection_badge_uncheck.esm.js +++ b/account_reconcile_oca/static/src/js/widgets/selection_badge_uncheck.esm.js @@ -4,6 +4,7 @@ import { preloadSelection, } from "@web/views/fields/badge_selection/badge_selection_field"; import {registry} from "@web/core/registry"; +import {standardFieldProps} from "@web/views/fields/standard_field_props"; export class FieldSelectionBadgeUncheck extends BadgeSelectionField { async onChange(value) { @@ -19,9 +20,17 @@ export class FieldSelectionBadgeUncheck extends BadgeSelectionField { } } +FieldSelectionBadgeUncheck.props = {...standardFieldProps}; FieldSelectionBadgeUncheck.supportedTypes = ["many2one", "selection"]; FieldSelectionBadgeUncheck.additionalClasses = ["o_field_selection_badge"]; -registry.category("fields").add("selection_badge_uncheck", FieldSelectionBadgeUncheck); + +export const FieldSelectionBadgeUncheckField = { + component: FieldSelectionBadgeUncheck, + supportedTypes: ["many2one"], +}; +registry + .category("fields") + .add("selection_badge_uncheck", FieldSelectionBadgeUncheckField); registry.category("preloadedData").add("selection_badge_uncheck", { loadOnTypes: ["many2one"], diff --git a/account_reconcile_oca/static/src/xml/reconcile.xml b/account_reconcile_oca/static/src/xml/reconcile.xml index 43af10d1..7fbe4632 100644 --- a/account_reconcile_oca/static/src/xml/reconcile.xml +++ b/account_reconcile_oca/static/src/xml/reconcile.xml @@ -48,7 +48,7 @@ >Create - + - - + @@ -307,11 +307,11 @@ {'default_journal_id': active_id, 'search_default_not_reconciled': True, 'view_ref': 'account_reconcile_oca.bank_statement_line_form_reconcile_view'} - tree + kanban

@@ -326,11 +326,11 @@ {'default_journal_id': active_id, 'view_ref': 'account_reconcile_oca.bank_statement_line_form_reconcile_view'} - tree + kanban

@@ -348,11 +348,11 @@ {'default_journal_id': active_id, 'search_default_to_check': True, 'view_ref': 'account_reconcile_oca.bank_statement_line_form_reconcile_view'} - tree + kanban

@@ -368,11 +368,11 @@ Reconcile bank statement lines account.bank.statement.line {'search_default_move_id': id} - tree + kanban

diff --git a/account_reconcile_oca/views/account_move_line.xml b/account_reconcile_oca/views/account_move_line.xml index 006807f9..bef2829b 100644 --- a/account_reconcile_oca/views/account_move_line.xml +++ b/account_reconcile_oca/views/account_move_line.xml @@ -8,7 +8,12 @@ account.move.line 99 - +