diff --git a/account_reconciliation_widget/models/account_bank_statement.py b/account_reconciliation_widget/models/account_bank_statement.py index d7d3975a..b654ca11 100644 --- a/account_reconciliation_widget/models/account_bank_statement.py +++ b/account_reconciliation_widget/models/account_bank_statement.py @@ -222,7 +222,6 @@ class AccountBankStatementLine(models.Model): aml_obj.with_context(check_move_validity=False).create(liquidity_aml_dict) self.sequence = self.statement_id.line_ids.ids.index(self.id) + 1 - self.move_id.ref = self._get_move_ref(self.statement_id.name) counterpart_moves = counterpart_moves | self.move_id # Complete dicts to create both counterpart move lines and write-offs @@ -246,6 +245,9 @@ class AccountBankStatementLine(models.Model): if aml_dict["move_line"].partner_id.id: aml_dict["partner_id"] = aml_dict["move_line"].partner_id.id aml_dict["account_id"] = aml_dict["move_line"].account_id.id + aml_dict["analytic_account_id"] = ( + aml_dict["move_line"].analytic_account_id.id or False + ) counterpart_move_line = aml_dict.pop("move_line") new_aml = aml_obj.with_context(check_move_validity=False).create(aml_dict) @@ -272,12 +274,6 @@ class AccountBankStatementLine(models.Model): return counterpart_moves - def _get_move_ref(self, move_ref): - ref = move_ref or "" - if self.ref: - ref = move_ref + " - " + self.ref if move_ref else self.ref - return ref - def _prepare_move_line_for_currency(self, aml_dict, date): self.ensure_one() company_currency = self.journal_id.company_id.currency_id diff --git a/account_reconciliation_widget/models/reconciliation_widget.py b/account_reconciliation_widget/models/reconciliation_widget.py index 8a5bae60..34150052 100644 --- a/account_reconciliation_widget/models/reconciliation_widget.py +++ b/account_reconciliation_widget/models/reconciliation_widget.py @@ -42,8 +42,13 @@ class AccountReconciliation(models.AbstractModel): ) del aml_dict["counterpart_aml_id"] + vals = {} if datum.get("partner_id") is not None: - st_line.write({"partner_id": datum["partner_id"]}) + vals["partner_id"] = datum["partner_id"] + if datum.get("ref") is not None: + vals["ref"] = datum["ref"] + if vals: + st_line.write(vals) ctx["default_to_check"] = datum.get("to_check") moves = st_line.with_context(ctx).process_reconciliation( @@ -906,6 +911,7 @@ class AccountReconciliation(models.AbstractModel): "already_paid": line.account_id.internal_type == "liquidity", "account_code": line.account_id.code, "account_name": line.account_id.name, + "analytic_account_code": line.analytic_account_id.display_name or "", "account_type": line.account_id.internal_type, "date_maturity": format_date(self.env, line.date_maturity), "date": format_date(self.env, line.date), @@ -1016,6 +1022,8 @@ class AccountReconciliation(models.AbstractModel): """Returns the data required by the bank statement reconciliation widget to display a statement line""" + group_analytic = self.env.user.has_group("analytic.group_analytic_accounting") + group_analytic_tags = self.env.user.has_group("analytic.group_analytic_tags") statement_currency = ( st_line.journal_id.currency_id or st_line.journal_id.company_id.currency_id ) @@ -1062,6 +1070,8 @@ class AccountReconciliation(models.AbstractModel): "amount_currency": amount_currency, "has_no_partner": not st_line.partner_id.id, "company_id": st_line.company_id.id, + "group_analytic_accounting": group_analytic, + "group_analytic_tags": group_analytic_tags, } if st_line.partner_id: data["open_balance_account_id"] = ( diff --git a/account_reconciliation_widget/static/src/js/reconciliation/reconciliation_action.js b/account_reconciliation_widget/static/src/js/reconciliation/reconciliation_action.js index 7aeb9dbe..b057cd86 100644 --- a/account_reconciliation_widget/static/src/js/reconciliation/reconciliation_action.js +++ b/account_reconciliation_widget/static/src/js/reconciliation/reconciliation_action.js @@ -21,6 +21,7 @@ odoo.define("account.ReconciliationClientAction", function (require) { change_filter: "_onAction", change_offset: "_onAction", change_partner: "_onAction", + change_ref: "_onAction", add_proposition: "_onAction", remove_proposition: "_onAction", update_proposition: "_onAction", @@ -86,6 +87,7 @@ odoo.define("account.ReconciliationClientAction", function (require) { this._super.apply(this, arguments); this.action_manager = parent; this.params = params; + this.notifications = params.context.notifications || []; this.searchModelConfig.modelName = "account.bank.statement.line"; this.controlPanelProps.cp_content = {}; this.model = new this.config.Model(this, { @@ -157,6 +159,7 @@ odoo.define("account.ReconciliationClientAction", function (require) { valuemax: self.model.valuemax, defaultDisplayQty: self.model.defaultDisplayQty, title: title, + notifications: self.notifications, }); }); }); diff --git a/account_reconciliation_widget/static/src/js/reconciliation/reconciliation_model.js b/account_reconciliation_widget/static/src/js/reconciliation/reconciliation_model.js index d238b1ab..62f5b7ae 100644 --- a/account_reconciliation_widget/static/src/js/reconciliation/reconciliation_model.js +++ b/account_reconciliation_widget/static/src/js/reconciliation/reconciliation_model.js @@ -298,6 +298,13 @@ odoo.define("account.ReconciliationModel", function (require) { ); }); }, + // eslint-disable-next-line no-unused-vars + changeRef: function (handle, ref, preserveMode) { + var line = this.getLine(handle); + line.st_line.ref = ref; + return Promise.resolve(); + }, + /** * Close the statement * @returns {Promise} resolves to the res_id of the closed statements @@ -479,6 +486,7 @@ odoo.define("account.ReconciliationModel", function (require) { self.lines[handle] = { id: res.st_line.id, partner_id: res.st_line.partner_id, + ref: res.st_line.ref, handle: handle, reconciled: false, mode: "inactive", @@ -521,11 +529,22 @@ odoo.define("account.ReconciliationModel", function (require) { _.pluck(accounts, "code") ); }); + var def_analytic_account = this._rpc({ + model: "account.analytic.account", + method: "search_read", + fields: ["display_name"], + }).then(function (accounts) { + self.analytic_accounts = _.object( + _.pluck(accounts, "id"), + _.pluck(accounts, "display_name") + ); + }); var def_taxes = self._loadTaxes(); return Promise.all([ def_statement, def_reconcileModel, def_account, + def_analytic_account, def_taxes, ]).then(function () { _.each(self.lines, function (line) { @@ -888,6 +907,12 @@ odoo.define("account.ReconciliationModel", function (require) { ? this.accounts[prop.account_id.id] : ""; } + if ("analytic_account_id" in values) { + prop.analytic_account_code = prop.analytic_account_id + ? this.analytic_accounts[prop.analytic_account_id.id] + : ""; + } + if ("amount" in values) { prop.base_amount = values.amount; if (prop.reconcileModelId) { @@ -967,6 +992,7 @@ odoo.define("account.ReconciliationModel", function (require) { Promise.resolve(computeLinePromise).then(function () { var values_dict = { partner_id: line.st_line.partner_id, + ref: line.st_line.ref, counterpart_aml_dicts: _.map( _.filter(props, function (prop) { return !isNaN(prop.id) && !prop.is_liquidity_line; @@ -1589,6 +1615,7 @@ odoo.define("account.ReconciliationModel", function (require) { values = values || {}; var today = new moment().utc().format(); var account = this._formatNameGet(values.account_id); + var analytic_account = this._formatNameGet(values.analytic_account_id); var formatOptions = { currency_id: line.st_line.currency_id, }; @@ -1632,7 +1659,10 @@ odoo.define("account.ReconciliationModel", function (require) { label: values.label || line.st_line.payment_ref, account_id: account, account_code: account ? this.accounts[account.id] : "", - analytic_account_id: this._formatNameGet(values.analytic_account_id), + analytic_account_id: analytic_account, + analytic_account_code: analytic_account + ? this.analytic_accounts[analytic_account.id] + : "", analytic_tag_ids: this._formatMany2ManyTags( values.analytic_tag_ids || [] ), diff --git a/account_reconciliation_widget/static/src/js/reconciliation/reconciliation_renderer.js b/account_reconciliation_widget/static/src/js/reconciliation/reconciliation_renderer.js index 1dc17e08..7c31d1a4 100644 --- a/account_reconciliation_widget/static/src/js/reconciliation/reconciliation_renderer.js +++ b/account_reconciliation_widget/static/src/js/reconciliation/reconciliation_renderer.js @@ -38,6 +38,9 @@ odoo.define("account.ReconciliationRenderer", function (require) { var defs = [this._super.apply(this, arguments)]; this.time = Date.now(); this.$progress = $(""); + if (this._initialState.notifications.length > 0) { + this._renderNotifications(this._initialState.notifications); + } return Promise.all(defs); }, @@ -325,20 +328,31 @@ odoo.define("account.ReconciliationRenderer", function (require) { } ), }; - self.fields.partner_id.insertAfter( - self.$(".accounting_view caption .o_buttons") + self.fields.partner_id.insertBefore( + self.$(".accounting_view caption .caption-input") ); }); - var def3 = session - .user_has_group("analytic.group_analytic_tags") - .then(function (has_group) { - self.group_tags = has_group; - }); - var def4 = session - .user_has_group("analytic.group_analytic_accounting") - .then(function (has_group) { - self.group_acc = has_group; - }); + // Ref + var def5 = this._makeRefRecord(this._initialState.st_line.ref).then( + function (recordID) { + self.fields.ref = new basic_fields.FieldChar( + self, + "ref", + self.model.get(recordID), + { + mode: "edit", + attrs: { + placeholder: + self._initialState.st_line.ref || _t("Reference"), + }, + } + ); + self.fields.ref.prependTo( + self.$(".accounting_view caption .caption-input") + ); + } + ); + $('') .appendTo(this.$("thead .cell_info_popover")) .attr( @@ -360,7 +374,7 @@ odoo.define("account.ReconciliationRenderer", function (require) { toggle: "popover", }); var def2 = this._super.apply(this, arguments); - return Promise.all([def1, def2, def3, def4]); + return Promise.all([def1, def2, def5]); }, // -------------------------------------------------------------------------- @@ -402,6 +416,12 @@ odoo.define("account.ReconciliationRenderer", function (require) { self.$el.attr("data-partner", state.st_line.partner_id); }); + // Ref + this._makeRefRecord(state.st_line.ref).then(function (recordID) { + self.fields.ref.reset(self.model.get(recordID)); + self.$el.attr("data-ref", state.st_line.ref); + }); + // Mode this.$el.data("mode", state.mode).attr("data-mode", state.mode); this.$(".o_notebook li a").attr("aria-selected", false); @@ -574,6 +594,7 @@ odoo.define("account.ReconciliationRenderer", function (require) { } if (fieldName === "tax_ids") { if ( + state.createForm[fieldName] === undefined || !state.createForm[fieldName].length || state.createForm[fieldName].length > 1 ) { @@ -662,6 +683,17 @@ odoo.define("account.ReconciliationRenderer", function (require) { }); }, + _makeRefRecord: function (ref) { + var field = { + type: "char", + name: "ref", + }; + if (ref) { + field.value = ref; + } + return this.model.makeRecord("account.bank.statement.line", [field], {}); + }, + /** * Create account_id, tax_ids, analytic_account_id, analytic_tag_ids, label and amount fields * @@ -714,6 +746,10 @@ odoo.define("account.ReconciliationRenderer", function (require) { type: "char", name: "label", }, + { + type: "char", + name: "ref", + }, { type: "float", name: "amount", @@ -815,8 +851,6 @@ odoo.define("account.ReconciliationRenderer", function (require) { var $create = $( qweb.render("reconciliation.line.create", { state: state, - group_tags: self.group_tags, - group_acc: self.group_acc, }) ); @@ -945,6 +979,9 @@ odoo.define("account.ReconciliationRenderer", function (require) { if (fieldName === "partner_id") { var partner_id = event.data.changes.partner_id; this.trigger_up("change_partner", {data: partner_id}); + } else if (fieldName === "ref") { + var ref = event.data.changes.ref; + this.trigger_up("change_ref", {data: ref}); } else { if (event.data.changes.amount && isNaN(event.data.changes.amount)) { return; diff --git a/account_reconciliation_widget/static/src/scss/account_reconciliation.scss b/account_reconciliation_widget/static/src/scss/account_reconciliation.scss index f776eebe..3fbf6731 100644 --- a/account_reconciliation_widget/static/src/scss/account_reconciliation.scss +++ b/account_reconciliation_widget/static/src/scss/account_reconciliation.scss @@ -56,6 +56,16 @@ .strike_amount { text-decoration: line-through; } + .move_name { + font-size: 80%; + margin-left: 1em; + display: flex; + align-items: center; + } + .caption-input { + margin-left: 1em; + display: inline-flex; + } tbody tr:hover .cell_account_code::before { content: "\f068"; font-family: FontAwesome; @@ -146,6 +156,9 @@ width: 80px; padding-left: 5px; } + .cell_analytic_account { + width: 230px; + } .cell_due_date { width: 100px; } @@ -177,6 +190,7 @@ .cell_label, .cell_due_date, .cell_account_code, + .cell_analytic_account, .cell_info_popover { box-shadow: 0 1px 0 #eaeaea; } diff --git a/account_reconciliation_widget/static/src/xml/account_reconciliation.xml b/account_reconciliation_widget/static/src/xml/account_reconciliation.xml index 668421af..c9d667df 100644 --- a/account_reconciliation_widget/static/src/xml/account_reconciliation.xml +++ b/account_reconciliation_widget/static/src/xml/account_reconciliation.xml @@ -126,6 +126,9 @@
+ @@ -384,13 +399,19 @@ >Taxes - + - + @@ -498,6 +519,12 @@ +
+
+ +
+ Open balanceChoose counterpart or Create Write-off