From 119ac683ffcd3ffcaabadc318af28712dd508593 Mon Sep 17 00:00:00 2001 From: Ajmal Cybro Date: Mon, 18 Jan 2021 17:41:23 +0530 Subject: [PATCH] [IMP] Reconciliation Widget added --- base_accounting_kit/README.rst | 2 +- base_accounting_kit/__manifest__.py | 11 +- base_accounting_kit/doc/changelog.md | 5 + base_accounting_kit/models/__init__.py | 1 + base_accounting_kit/models/account_journal.py | 22 + base_accounting_kit/models/account_payment.py | 22 + .../models/payment_matching.py | 929 ++++++++ .../static/description/banner.gif | Bin 109768 -> 114270 bytes .../static/description/index.html | 15 + .../static/src/js/payment_matching.js | 505 +++++ .../static/src/js/payment_model.js | 1881 +++++++++++++++++ .../static/src/js/payment_render.js | 929 ++++++++ .../static/src/xml/payment_matching.xml | 402 ++++ base_accounting_kit/views/assets.xml | 3 + .../views/payment_matching.xml | 34 + 15 files changed, 4757 insertions(+), 4 deletions(-) create mode 100644 base_accounting_kit/models/payment_matching.py create mode 100644 base_accounting_kit/static/src/js/payment_matching.js create mode 100644 base_accounting_kit/static/src/js/payment_model.js create mode 100644 base_accounting_kit/static/src/js/payment_render.js create mode 100644 base_accounting_kit/static/src/xml/payment_matching.xml create mode 100644 base_accounting_kit/views/payment_matching.xml diff --git a/base_accounting_kit/README.rst b/base_accounting_kit/README.rst index 8616c21b9..e78857144 100644 --- a/base_accounting_kit/README.rst +++ b/base_accounting_kit/README.rst @@ -1,5 +1,5 @@ Accounting Kit -============================= +============== * Full accounting kit for Odoo 14 community editions Installation diff --git a/base_accounting_kit/__manifest__.py b/base_accounting_kit/__manifest__.py index 7276aa020..ee0ebfb4c 100644 --- a/base_accounting_kit/__manifest__.py +++ b/base_accounting_kit/__manifest__.py @@ -22,7 +22,7 @@ { 'name': 'Odoo 14 Full Accounting Kit', - 'version': '14.0.1.4.4', + 'version': '14.0.2.4.4', 'category': 'Accounting', 'live_test_url': 'https://www.youtube.com/watch?v=peAp2Tx_XIs', 'summary': """ Asset and Budget Management, @@ -39,7 +39,10 @@ Full Accounting, Complete Accounting, Odoo Community Accounting, Accounting for odoo 14, Full Accounting Package, - Financial Reports, Financial Report for Odoo 14 + Financial Reports, Financial Report for Odoo 14, + Reconciliation Widget, + Reconciliation Widget For Odoo14, + Payments Matching """, 'author': ' Odoo SA,Cybrosys Techno Solutions', 'website': "https://www.cybrosys.com", @@ -72,6 +75,7 @@ 'views/account_move_views.xml', 'views/account_asset_templates.xml', 'views/product_template_views.xml', + 'views/payment_matching.xml', 'wizard/financial_report.xml', 'wizard/general_ledger.xml', 'wizard/partner_ledger.xml', @@ -99,7 +103,8 @@ 'report/report.xml', ], 'qweb': [ - 'static/src/xml/template.xml' + 'static/src/xml/template.xml', + 'static/src/xml/payment_matching.xml' ], 'license': 'LGPL-3', 'images': ['static/description/banner.gif'], diff --git a/base_accounting_kit/doc/changelog.md b/base_accounting_kit/doc/changelog.md index 378ac2104..bf26547f9 100644 --- a/base_accounting_kit/doc/changelog.md +++ b/base_accounting_kit/doc/changelog.md @@ -25,4 +25,9 @@ #### UPDT - Removed warnings, Updated access rules. +#### 18.01.2021 +#### Version 14.0.2.4.4 +#### UPDT +- Reconciliation Widget Added. + diff --git a/base_accounting_kit/models/__init__.py b/base_accounting_kit/models/__init__.py index 9562f352a..646509e4b 100644 --- a/base_accounting_kit/models/__init__.py +++ b/base_accounting_kit/models/__init__.py @@ -33,3 +33,4 @@ from . import recurring_payments from . import res_config_settings from . import res_partner from . import account_dashboard +from . import payment_matching diff --git a/base_accounting_kit/models/account_journal.py b/base_accounting_kit/models/account_journal.py index 698a590a1..4a13eaefa 100755 --- a/base_accounting_kit/models/account_journal.py +++ b/base_accounting_kit/models/account_journal.py @@ -26,6 +26,28 @@ from odoo import models, api class AccountJournal(models.Model): _inherit = "account.journal" + def action_open_reconcile(self): + if self.type in ['bank', 'cash']: + # Open reconciliation view for bank statements belonging to this journal + bank_stmt = self.env['account.bank.statement'].search([('journal_id', 'in', self.ids)]).mapped('line_ids') + return { + 'type': 'ir.actions.client', + 'tag': 'bank_statement_reconciliation_view', + 'context': {'statement_line_ids': bank_stmt.ids, 'company_ids': self.mapped('company_id').ids}, + } + else: + # Open reconciliation view for customers/suppliers + action_context = {'show_mode_selector': False, 'company_ids': self.mapped('company_id').ids} + if self.type == 'sale': + action_context.update({'mode': 'customers'}) + elif self.type == 'purchase': + action_context.update({'mode': 'suppliers'}) + return { + 'type': 'ir.actions.client', + 'tag': 'manual_reconciliation_view', + 'context': action_context, + } + @api.depends('outbound_payment_method_ids') def _compute_check_printing_payment_method_selected(self): for journal in self: diff --git a/base_accounting_kit/models/account_payment.py b/base_accounting_kit/models/account_payment.py index 5a3e2f9e7..cb0b9e9e7 100755 --- a/base_accounting_kit/models/account_payment.py +++ b/base_accounting_kit/models/account_payment.py @@ -59,6 +59,28 @@ class AccountPayment(models.Model): help='Effective date of PDC', copy=False, default=False) + def open_payment_matching_screen(self): + # Open reconciliation view for customers/suppliers + move_line_id = False + for move_line in self.line_ids: + if move_line.account_id.reconcile: + move_line_id = move_line.id + break + if not self.partner_id: + raise UserError(_("Payments without a customer can't be matched")) + action_context = {'company_ids': [self.company_id.id], 'partner_ids': [self.partner_id.commercial_partner_id.id]} + if self.partner_type == 'customer': + action_context.update({'mode': 'customers'}) + elif self.partner_type == 'supplier': + action_context.update({'mode': 'suppliers'}) + if move_line_id: + action_context.update({'move_line_id': move_line_id}) + return { + 'type': 'ir.actions.client', + 'tag': 'manual_reconciliation_view', + 'context': action_context, + } + def print_checks(self): """ Check that the recordset is valid, set the payments state to sent and call print_checks() """ diff --git a/base_accounting_kit/models/payment_matching.py b/base_accounting_kit/models/payment_matching.py new file mode 100644 index 000000000..7f184da35 --- /dev/null +++ b/base_accounting_kit/models/payment_matching.py @@ -0,0 +1,929 @@ +# -*- coding: utf-8 -*- + +import copy +from odoo import api, fields, models, _ +from odoo.exceptions import UserError +from odoo.osv import expression +from odoo.tools.misc import formatLang, format_date, parse_date + + +class AccountReconciliation(models.AbstractModel): + _name = 'account.reconciliation.widget' + _description = 'Account Reconciliation widget' + + #################################################### + # Public + #################################################### + + @api.model + def process_bank_statement_line(self, st_line_ids, data): + """ Handles data sent from the bank statement reconciliation widget + (and can otherwise serve as an old-API bridge) + + :param st_line_ids + :param list of dicts data: must contains the keys + 'counterpart_aml_dicts', 'payment_aml_ids' and 'new_aml_dicts', + whose value is the same as described in process_reconciliation + except that ids are used instead of recordsets. + :returns dict: used as a hook to add additional keys. + """ + st_lines = self.env['account.bank.statement.line'].browse(st_line_ids) + AccountMoveLine = self.env['account.move.line'] + ctx = dict(self._context, force_price_include=False) + + processed_moves = self.env['account.move'] + for st_line, datum in zip(st_lines, copy.deepcopy(data)): + payment_aml_rec = AccountMoveLine.browse(datum.get('payment_aml_ids', [])) + + for aml_dict in datum.get('counterpart_aml_dicts', []): + aml_dict['move_line'] = AccountMoveLine.browse(aml_dict['counterpart_aml_id']) + del aml_dict['counterpart_aml_id'] + + if datum.get('partner_id') is not None: + st_line.write({'partner_id': datum['partner_id']}) + + ctx['default_to_check'] = datum.get('to_check') + moves = st_line.with_context(ctx).reconcile(datum.get('lines_vals_list', []), to_check=datum.get('to_check', False)) + + return {'moves': processed_moves.ids, 'statement_line_ids': processed_moves.mapped('line_ids.statement_line_id').ids} + + @api.model + def get_move_lines_for_bank_statement_line(self, st_line_id, partner_id=None, excluded_ids=None, search_str=False, offset=0, limit=None, mode=None): + """ Returns move lines for the bank statement reconciliation widget, + formatted as a list of dicts + + :param st_line_id: ids of the statement lines + :param partner_id: optional partner id to select only the moves + line corresponding to the partner + :param excluded_ids: optional move lines ids excluded from the + result + :param search_str: optional search (can be the amout, display_name, + partner name, move line name) + :param offset: useless but kept in stable to preserve api + :param limit: number of the result to search + :param mode: 'rp' for receivable/payable or 'other' + """ + st_line = self.env['account.bank.statement.line'].browse(st_line_id) + + # Blue lines = payment on bank account not assigned to a statement yet + aml_accounts = [ + st_line.journal_id.default_account_id.id + ] + + if partner_id is None: + partner_id = st_line.partner_id.id + + domain = self._domain_move_lines_for_reconciliation(st_line, aml_accounts, partner_id, excluded_ids=excluded_ids, search_str=search_str, mode=mode) + recs_count = self.env['account.move.line'].search_count(domain) + + from_clause, where_clause, where_clause_params = self.env['account.move.line']._where_calc(domain).get_sql() + query_str = ''' + SELECT "account_move_line".id FROM {from_clause} + {where_str} + ORDER BY ("account_move_line".debit - "account_move_line".credit) = {amount} DESC, + "account_move_line".date_maturity ASC, + "account_move_line".id ASC + {limit_str} + '''.format( + from_clause=from_clause, + where_str=where_clause and (" WHERE %s" % where_clause) or '', + amount=st_line.amount, + limit_str=limit and ' LIMIT %s' or '', + ) + params = where_clause_params + (limit and [limit] or []) + self.env['account.move'].flush() + self.env['account.move.line'].flush() + self.env['account.bank.statement'].flush() + self._cr.execute(query_str, params) + res = self._cr.fetchall() + + aml_recs = self.env['account.move.line'].browse([i[0] for i in res]) + target_currency = st_line.currency_id or st_line.journal_id.currency_id or st_line.journal_id.company_id.currency_id + return self._prepare_move_lines(aml_recs, target_currency=target_currency, target_date=st_line.date, recs_count=recs_count) + + @api.model + def _get_bank_statement_line_partners(self, st_lines): + params = [] + + # Add the res.partner.ban's IR rules. In case partners are not shared between companies, + # identical bank accounts may exist in a company we don't have access to. + ir_rules_query = self.env['res.partner.bank']._where_calc([]) + self.env['res.partner.bank']._apply_ir_rules(ir_rules_query, 'read') + from_clause, where_clause, where_clause_params = ir_rules_query.get_sql() + if where_clause: + where_bank = ('AND %s' % where_clause).replace('res_partner_bank', 'bank') + params += where_clause_params + else: + where_bank = '' + + # Add the res.partner's IR rules. In case partners are not shared between companies, + # identical partners may exist in a company we don't have access to. + ir_rules_query = self.env['res.partner']._where_calc([]) + self.env['res.partner']._apply_ir_rules(ir_rules_query, 'read') + from_clause, where_clause, where_clause_params = ir_rules_query.get_sql() + if where_clause: + where_partner = ('AND %s' % where_clause).replace('res_partner', 'p3') + params += where_clause_params + else: + where_partner = '' + + query = ''' + SELECT + st_line.id AS id, + COALESCE(p1.id,p2.id,p3.id) AS partner_id + FROM account_bank_statement_line st_line + JOIN account_move move ON move.id = st_line.move_id + ''' + query += "LEFT JOIN res_partner_bank bank ON bank.id = move.partner_bank_id OR bank.sanitized_acc_number ILIKE regexp_replace(st_line.account_number, '\W+', '', 'g') %s\n" % (where_bank) + query += 'LEFT JOIN res_partner p1 ON st_line.partner_id=p1.id \n' + query += 'LEFT JOIN res_partner p2 ON bank.partner_id=p2.id \n' + # By definition the commercial partner_id doesn't have a parent_id set + query += 'LEFT JOIN res_partner p3 ON p3.name ILIKE st_line.partner_name %s AND p3.parent_id is NULL \n' % (where_partner) + query += 'WHERE st_line.id IN %s' + + params += [tuple(st_lines.ids)] + + self._cr.execute(query, params) + + result = {} + for res in self._cr.dictfetchall(): + result[res['id']] = res['partner_id'] + return result + + @api.model + def get_bank_statement_line_data(self, st_line_ids, excluded_ids=None): + """ Returns the data required to display a reconciliation widget, for + each statement line in self + + :param st_line_id: ids of the statement lines + :param excluded_ids: optional move lines ids excluded from the + result + """ + results = { + 'lines': [], + 'value_min': 0, + 'value_max': 0, + 'reconciled_aml_ids': [], + } + + if not st_line_ids: + return results + + excluded_ids = excluded_ids or [] + + # Make a search to preserve the table's order. + bank_statement_lines = self.env['account.bank.statement.line'].search([('id', 'in', st_line_ids)]) + results['value_max'] = len(bank_statement_lines) + reconcile_model = self.env['account.reconcile.model'].search([('rule_type', '!=', 'writeoff_button')]) + + # Search for missing partners when opening the reconciliation widget. + if bank_statement_lines: + partner_map = self._get_bank_statement_line_partners(bank_statement_lines) + matching_amls = reconcile_model._apply_rules(bank_statement_lines, excluded_ids=excluded_ids, partner_map=partner_map) + + # Iterate on st_lines to keep the same order in the results list. + bank_statements_left = self.env['account.bank.statement'] + for line in bank_statement_lines: + if matching_amls[line.id].get('status') == 'reconciled': + reconciled_move_lines = matching_amls[line.id].get('reconciled_lines') + results['value_min'] += 1 + results['reconciled_aml_ids'] += reconciled_move_lines and reconciled_move_lines.ids or [] + else: + aml_ids = matching_amls[line.id]['aml_ids'] + bank_statements_left += line.statement_id + target_currency = line.currency_id or line.journal_id.currency_id or line.journal_id.company_id.currency_id + + amls = aml_ids and self.env['account.move.line'].browse(aml_ids) + line_vals = { + 'st_line': self._get_statement_line(line), + 'reconciliation_proposition': aml_ids and self._prepare_move_lines(amls, target_currency=target_currency, target_date=line.date) or [], + 'model_id': matching_amls[line.id].get('model') and matching_amls[line.id]['model'].id, + 'write_off': matching_amls[line.id].get('status') == 'write_off', + } + if not line.partner_id and partner_map.get(line.id): + partner = self.env['res.partner'].browse(partner_map[line.id]) + line_vals.update({ + 'partner_id': partner.id, + 'partner_name': partner.name, + }) + results['lines'].append(line_vals) + + return results + + @api.model + def get_bank_statement_data(self, bank_statement_line_ids, srch_domain=[]): + """ Get statement lines of the specified statements or all unreconciled + statement lines and try to automatically reconcile them / find them + a partner. + Return ids of statement lines left to reconcile and other data for + the reconciliation widget. + + :param bank_statement_line_ids: ids of the bank statement lines + """ + if not bank_statement_line_ids: + return {} + domain = [['id', 'in', tuple(bank_statement_line_ids)], ('is_reconciled', '=', False)] + srch_domain + bank_statement_lines = self.env['account.bank.statement.line'].search(domain) + bank_statements = bank_statement_lines.mapped('statement_id') + + results = self.get_bank_statement_line_data(bank_statement_lines.ids) + bank_statement_lines_left = self.env['account.bank.statement.line'].browse([line['st_line']['id'] for line in results['lines']]) + bank_statements_left = bank_statement_lines_left.mapped('statement_id') + + results.update({ + 'statement_name': len(bank_statements_left) == 1 and bank_statements_left.name or False, + 'journal_id': bank_statements and bank_statements[0].journal_id.id or False, + 'notifications': [] + }) + + if len(results['lines']) < len(bank_statement_lines): + results['notifications'].append({ + 'type': 'info', + 'template': 'reconciliation.notification.reconciled', + 'reconciled_aml_ids': results['reconciled_aml_ids'], + 'nb_reconciled_lines': results['value_min'], + 'details': { + 'name': _('Journal Items'), + 'model': 'account.move.line', + 'ids': results['reconciled_aml_ids'], + } + }) + + return results + + @api.model + def get_move_lines_for_manual_reconciliation(self, account_id, partner_id=False, excluded_ids=None, search_str=False, offset=0, limit=None, target_currency_id=False): + """ Returns unreconciled move lines for an account or a partner+account, formatted for the manual reconciliation widget """ + + Account_move_line = self.env['account.move.line'] + Account = self.env['account.account'] + Currency = self.env['res.currency'] + + domain = self._domain_move_lines_for_manual_reconciliation(account_id, partner_id, excluded_ids, search_str) + recs_count = Account_move_line.search_count(domain) + lines = Account_move_line.search(domain, limit=limit, order="date_maturity desc, id desc") + if target_currency_id: + target_currency = Currency.browse(target_currency_id) + else: + account = Account.browse(account_id) + target_currency = account.currency_id or account.company_id.currency_id + return self._prepare_move_lines(lines, target_currency=target_currency,recs_count=recs_count) + + @api.model + def get_all_data_for_manual_reconciliation(self, partner_ids, account_ids): + """ Returns the data required for the invoices & payments matching of partners/accounts. + If an argument is None, fetch all related reconciliations. Use [] to fetch nothing. + """ + MoveLine = self.env['account.move.line'] + aml_ids = self._context.get('active_ids') and self._context.get('active_model') == 'account.move.line' and tuple(self._context.get('active_ids')) + if aml_ids: + aml = MoveLine.browse(aml_ids) + aml._check_reconcile_validity() + account = aml[0].account_id + currency = account.currency_id or account.company_id.currency_id + return { + 'accounts': [{ + 'reconciliation_proposition': self._prepare_move_lines(aml, target_currency=currency), + 'company_id': account.company_id.id, + 'currency_id': currency.id, + 'mode': 'accounts', + 'account_id': account.id, + 'account_name': account.name, + 'account_code': account.code, + }], + 'customers': [], + 'suppliers': [], + } + # If we have specified partner_ids, don't return the list of reconciliation for specific accounts as it will + # show entries that are not reconciled with other partner. Asking for a specific partner on a specific account + # is never done. + accounts_data = [] + if not partner_ids or not any(partner_ids): + accounts_data = self.get_data_for_manual_reconciliation('account', account_ids) + return { + 'customers': self.get_data_for_manual_reconciliation('partner', partner_ids, 'receivable'), + 'suppliers': self.get_data_for_manual_reconciliation('partner', partner_ids, 'payable'), + 'accounts': accounts_data, + } + + @api.model + def get_data_for_manual_reconciliation(self, res_type, res_ids=None, account_type=None): + """ Returns the data required for the invoices & payments matching of partners/accounts (list of dicts). + If no res_ids is passed, returns data for all partners/accounts that can be reconciled. + + :param res_type: either 'partner' or 'account' + :param res_ids: ids of the partners/accounts to reconcile, use None to fetch data indiscriminately + of the id, use [] to prevent from fetching any data at all. + :param account_type: if a partner is both customer and vendor, you can use 'payable' to reconcile + the vendor-related journal entries and 'receivable' for the customer-related entries. + """ + + Account = self.env['account.account'] + Partner = self.env['res.partner'] + + if res_ids is not None and len(res_ids) == 0: + # Note : this short-circuiting is better for performances, but also required + # since postgresql doesn't implement empty list (so 'AND id in ()' is useless) + return [] + res_ids = res_ids and tuple(res_ids) + + assert res_type in ('partner', 'account') + assert account_type in ('payable', 'receivable', None) + is_partner = res_type == 'partner' + res_alias = is_partner and 'p' or 'a' + aml_ids = self._context.get('active_ids') and self._context.get('active_model') == 'account.move.line' and tuple(self._context.get('active_ids')) + all_entries = self._context.get('all_entries', False) + all_entries_query = """ + AND EXISTS ( + SELECT NULL + FROM account_move_line l + JOIN account_move move ON l.move_id = move.id + JOIN account_journal journal ON l.journal_id = journal.id + WHERE l.account_id = a.id + {inner_where} + AND l.amount_residual != 0 + AND move.state = 'posted' + ) + """.format(inner_where=is_partner and 'AND l.partner_id = p.id' or ' ') + only_dual_entries_query = """ + AND EXISTS ( + SELECT NULL + FROM account_move_line l + JOIN account_move move ON l.move_id = move.id + JOIN account_journal journal ON l.journal_id = journal.id + WHERE l.account_id = a.id + {inner_where} + AND l.amount_residual > 0 + AND move.state = 'posted' + ) + AND EXISTS ( + SELECT NULL + FROM account_move_line l + JOIN account_move move ON l.move_id = move.id + JOIN account_journal journal ON l.journal_id = journal.id + WHERE l.account_id = a.id + {inner_where} + AND l.amount_residual < 0 + AND move.state = 'posted' + ) + """.format(inner_where=is_partner and 'AND l.partner_id = p.id' or ' ') + query = (""" + SELECT {select} account_id, account_name, account_code, max_date + FROM ( + SELECT {inner_select} + a.id AS account_id, + a.name AS account_name, + a.code AS account_code, + MAX(l.write_date) AS max_date + FROM + account_move_line l + RIGHT JOIN account_account a ON (a.id = l.account_id) + RIGHT JOIN account_account_type at ON (at.id = a.user_type_id) + {inner_from} + WHERE + a.reconcile IS TRUE + AND l.full_reconcile_id is NULL + {where1} + {where2} + {where3} + AND l.company_id = {company_id} + {where4} + {where5} + GROUP BY {group_by1} a.id, a.name, a.code {group_by2} + {order_by} + ) as s + {outer_where} + """.format( + select=is_partner and "partner_id, partner_name, to_char(last_time_entries_checked, 'YYYY-MM-DD') AS last_time_entries_checked," or ' ', + inner_select=is_partner and 'p.id AS partner_id, p.name AS partner_name, p.last_time_entries_checked AS last_time_entries_checked,' or ' ', + inner_from=is_partner and 'RIGHT JOIN res_partner p ON (l.partner_id = p.id)' or ' ', + where1=is_partner and ' ' or "AND ((at.type <> 'payable' AND at.type <> 'receivable') OR l.partner_id IS NULL)", + where2=account_type and "AND at.type = %(account_type)s" or '', + where3=res_ids and 'AND ' + res_alias + '.id in %(res_ids)s' or '', + company_id=self.env.company.id, + where4=aml_ids and 'AND l.id IN %(aml_ids)s' or ' ', + where5=all_entries and all_entries_query or only_dual_entries_query, + group_by1=is_partner and 'l.partner_id, p.id,' or ' ', + group_by2=is_partner and ', p.last_time_entries_checked' or ' ', + order_by=is_partner and 'ORDER BY p.last_time_entries_checked' or 'ORDER BY a.code', + outer_where=is_partner and 'WHERE (last_time_entries_checked IS NULL OR max_date > last_time_entries_checked)' or ' ', + )) + self.env['account.move.line'].flush() + self.env['account.account'].flush() + self.env.cr.execute(query, locals()) + + # Apply ir_rules by filtering out + rows = self.env.cr.dictfetchall() + ids = [x['account_id'] for x in rows] + allowed_ids = set(Account.browse(ids).ids) + rows = [row for row in rows if row['account_id'] in allowed_ids] + if is_partner: + ids = [x['partner_id'] for x in rows] + allowed_ids = set(Partner.browse(ids).ids) + rows = [row for row in rows if row['partner_id'] in allowed_ids] + + # Keep mode for future use in JS + if res_type == 'account': + mode = 'accounts' + else: + mode = 'customers' if account_type == 'receivable' else 'suppliers' + + # Fetch other data + for row in rows: + account = Account.browse(row['account_id']) + currency = account.currency_id or account.company_id.currency_id + row['currency_id'] = currency.id + partner_id = is_partner and row['partner_id'] or None + rec_prop = aml_ids and self.env['account.move.line'].browse(aml_ids) or self._get_move_line_reconciliation_proposition(account.id, partner_id) + row['reconciliation_proposition'] = self._prepare_move_lines(rec_prop, target_currency=currency) + row['mode'] = mode + row['company_id'] = account.company_id.id + + # Return the partners with a reconciliation proposition first, since they are most likely to + # be reconciled. + return [r for r in rows if r['reconciliation_proposition']] + [r for r in rows if not r['reconciliation_proposition']] + + @api.model + def process_move_lines(self, data): + """ Used to validate a batch of reconciliations in a single call + :param data: list of dicts containing: + - 'type': either 'partner' or 'account' + - 'id': id of the affected res.partner or account.account + - 'mv_line_ids': ids of existing account.move.line to reconcile + - 'new_mv_line_dicts': list of dicts containing values suitable for account_move_line.create() + """ + + Partner = self.env['res.partner'] + Account = self.env['account.account'] + + for datum in data: + if len(datum['mv_line_ids']) >= 1 or len(datum['mv_line_ids']) + len(datum['new_mv_line_dicts']) >= 2: + self._process_move_lines(datum['mv_line_ids'], datum['new_mv_line_dicts']) + + if datum['type'] == 'partner': + partners = Partner.browse(datum['id']) + partners.mark_as_reconciled() + + #################################################### + # Private + #################################################### + + def _str_domain_for_mv_line(self, search_str): + return [ + '|', ('account_id.code', 'ilike', search_str), + '|', ('move_id.name', 'ilike', search_str), + '|', ('move_id.ref', 'ilike', search_str), + '|', ('date_maturity', 'like', parse_date(self.env, search_str)), + '&', ('name', '!=', '/'), ('name', 'ilike', search_str) + ] + + @api.model + def _domain_move_lines(self, search_str): + """ Returns the domain from the search_str search + :param search_str: search string + """ + if not search_str: + return [] + str_domain = self._str_domain_for_mv_line(search_str) + if search_str[0] in ['-', '+']: + try: + amounts_str = search_str.split('|') + for amount_str in amounts_str: + amount = amount_str[0] == '-' and float(amount_str) or float(amount_str[1:]) + amount_domain = [ + '|', ('amount_residual', '=', amount), + '|', ('amount_residual_currency', '=', amount), + '|', (amount_str[0] == '-' and 'credit' or 'debit', '=', float(amount_str[1:])), + ('amount_currency', '=', amount), + ] + str_domain = expression.OR([str_domain, amount_domain]) + except: + pass + else: + try: + amount = float(search_str) + amount_domain = [ + '|', ('amount_residual', '=', amount), + '|', ('amount_residual_currency', '=', amount), + '|', ('amount_residual', '=', -amount), + '|', ('amount_residual_currency', '=', -amount), + '&', ('account_id.internal_type', '=', 'liquidity'), + '|', '|', '|', ('debit', '=', amount), ('credit', '=', amount), ('amount_currency', '=', amount), ('amount_currency', '=', -amount), + ] + str_domain = expression.OR([str_domain, amount_domain]) + except: + pass + return str_domain + + @api.model + def _domain_move_lines_for_reconciliation(self, st_line, aml_accounts, partner_id, excluded_ids=[], search_str=False, mode='rp'): + """ Return the domain for account.move.line records which can be used for bank statement reconciliation. + + :param aml_accounts: + :param partner_id: + :param excluded_ids: + :param search_str: + :param mode: 'rp' for receivable/payable or 'other' + """ + AccountMoveLine = self.env['account.move.line'] + + #Always exclude the journal items that have been marked as 'to be checked' in a former bank statement reconciliation + to_check_excluded = AccountMoveLine.search(AccountMoveLine._get_suspense_moves_domain()).ids + excluded_ids.extend(to_check_excluded) + + domain_reconciliation = [ + '&', '&', '&', + ('statement_line_id', '=', False), + ('account_id', 'in', aml_accounts), + ('payment_id', '<>', False), + ('balance', '!=', 0.0), + ] + + # default domain matching + domain_matching = [ + '&', '&', + ('reconciled', '=', False), + ('account_id.reconcile', '=', True), + ('balance', '!=', 0.0), + ] + + domain = expression.OR([domain_reconciliation, domain_matching]) + if partner_id: + domain = expression.AND([domain, [('partner_id', '=', partner_id)]]) + if mode == 'rp': + domain = expression.AND([domain, + [('account_id.internal_type', 'in', ['receivable', 'payable', 'liquidity'])] + ]) + else: + domain = expression.AND([domain, + [('account_id.internal_type', 'not in', ['receivable', 'payable', 'liquidity'])] + ]) + + # Domain factorized for all reconciliation use cases + if search_str: + str_domain = self._domain_move_lines(search_str=search_str) + str_domain = expression.OR([ + str_domain, + [('partner_id.name', 'ilike', search_str)] + ]) + domain = expression.AND([ + domain, + str_domain + ]) + + if excluded_ids: + domain = expression.AND([ + [('id', 'not in', excluded_ids)], + domain + ]) + # filter on account.move.line having the same company as the statement line + domain = expression.AND([domain, [('company_id', '=', st_line.company_id.id)]]) + + # take only moves in valid state. Draft is accepted only when "Post At" is set + # to "Bank Reconciliation" in the associated journal + domain_post_at = [ + + ('move_id.state', 'not in', ['draft', 'cancel']), + ] + domain = expression.AND([domain, domain_post_at]) + + # if st_line.company_id.account_bank_reconciliation_start: + # domain = expression.AND([domain, [('date', '>=', st_line.company_id.account_bank_reconciliation_start)]]) + return domain + + @api.model + def _domain_move_lines_for_manual_reconciliation(self, account_id, partner_id=False, excluded_ids=None, search_str=False): + """ Create domain criteria that are relevant to manual reconciliation. """ + domain = [ + ('reconciled', '=', False), + ('account_id', '=', account_id), + ('move_id.state', '=', 'posted') + ] + domain = expression.AND([domain, [('balance', '!=', 0.0)]]) + if partner_id: + domain = expression.AND([domain, [('partner_id', '=', partner_id)]]) + if excluded_ids: + domain = expression.AND([[('id', 'not in', excluded_ids)], domain]) + if search_str: + str_domain = self._domain_move_lines(search_str=search_str) + domain = expression.AND([domain, str_domain]) + # filter on account.move.line having the same company as the given account + account = self.env['account.account'].browse(account_id) + domain = expression.AND([domain, [('company_id', '=', account.company_id.id)]]) + return domain + + @api.model + def _prepare_move_lines(self, move_lines, target_currency=False, target_date=False, recs_count=0): + """ Returns move lines formatted for the manual/bank reconciliation widget + + :param move_line_ids: + :param target_currency: currency (browse) you want the move line debit/credit converted into + :param target_date: date to use for the monetary conversion + """ + context = dict(self._context or {}) + ret = [] + + for line in move_lines: + company_currency = line.company_id.currency_id + line_currency = (line.currency_id and line.amount_currency) and line.currency_id or company_currency + ret_line = { + 'id': line.id, + 'name': line.name and line.name != '/' and line.move_id.name != line.name and line.move_id.name + ': ' + line.name or line.move_id.name, + 'ref': line.move_id.ref or '', + # For reconciliation between statement transactions and already registered payments (eg. checks) + # NB : we don't use the 'reconciled' field because the line we're selecting is not the one that gets reconciled + 'account_id': [line.account_id.id, line.account_id.display_name], + 'already_paid': line.account_id.internal_type == 'liquidity', + 'account_code': line.account_id.code, + 'account_name': line.account_id.name, + 'account_type': line.account_id.internal_type, + 'date_maturity': format_date(self.env, line.date_maturity), + 'date': format_date(self.env, line.date), + 'journal_id': [line.journal_id.id, line.journal_id.display_name], + 'partner_id': line.partner_id.id, + 'partner_name': line.partner_id.name, + 'currency_id': line_currency.id, + } + + debit = line.debit + credit = line.credit + amount = line.amount_residual + amount_currency = line.amount_residual_currency + + # For already reconciled lines, don't use amount_residual(_currency) + if line.account_id.internal_type == 'liquidity': + amount = debit - credit + amount_currency = line.amount_currency + + target_currency = target_currency or company_currency + + # Use case: + # Let's assume that company currency is in USD and that we have the 3 following move lines + # Debit Credit Amount currency Currency + # 1) 25 0 0 NULL + # 2) 17 0 25 EUR + # 3) 33 0 25 YEN + # + # If we ask to see the information in the reconciliation widget in company currency, we want to see + # The following information + # 1) 25 USD (no currency information) + # 2) 17 USD [25 EUR] (show 25 euro in currency information, in the little bill) + # 3) 33 USD [25 YEN] (show 25 yen in currency information) + # + # If we ask to see the information in another currency than the company let's say EUR + # 1) 35 EUR [25 USD] + # 2) 25 EUR (no currency information) + # 3) 50 EUR [25 YEN] + # In that case, we have to convert the debit-credit to the currency we want and we show next to it + # the value of the amount_currency or the debit-credit if no amount currency + if target_currency == company_currency: + if line_currency == target_currency: + amount = amount + amount_currency = "" + total_amount = debit - credit + total_amount_currency = "" + else: + amount = amount + amount_currency = amount_currency + total_amount = debit - credit + total_amount_currency = line.amount_currency + + if target_currency != company_currency: + if line_currency == target_currency: + amount = amount_currency + amount_currency = "" + total_amount = line.amount_currency + total_amount_currency = "" + else: + amount_currency = line.currency_id and amount_currency or amount + company = line.account_id.company_id + date = target_date or line.date + amount = company_currency._convert(amount, target_currency, company, date) + total_amount = company_currency._convert((line.debit - line.credit), target_currency, company, date) + total_amount_currency = line.currency_id and line.amount_currency or (line.debit - line.credit) + + ret_line['recs_count'] = recs_count + ret_line['debit'] = amount > 0 and amount or 0 + ret_line['credit'] = amount < 0 and -amount or 0 + ret_line['amount_currency'] = amount_currency + ret_line['amount_str'] = formatLang(self.env, abs(amount), currency_obj=target_currency) + ret_line['total_amount_str'] = formatLang(self.env, abs(total_amount), currency_obj=target_currency) + ret_line['amount_currency_str'] = amount_currency and formatLang(self.env, abs(amount_currency), currency_obj=line_currency) or "" + ret_line['total_amount_currency_str'] = total_amount_currency and formatLang(self.env, abs(total_amount_currency), currency_obj=line_currency) or "" + ret.append(ret_line) + return ret + + @api.model + def _get_statement_line(self, st_line): + """ Returns the data required by the bank statement reconciliation widget to display a statement line """ + + statement_currency = st_line.journal_id.currency_id or st_line.journal_id.company_id.currency_id + if st_line.amount_currency and st_line.currency_id: + amount = st_line.amount_currency + amount_currency = st_line.amount + amount_currency_str = formatLang(self.env, abs(amount_currency), currency_obj=statement_currency) + else: + amount = st_line.amount + amount_currency = amount + amount_currency_str = "" + amount_str = formatLang(self.env, abs(amount), currency_obj=st_line.currency_id or statement_currency) + + data = { + 'id': st_line.id, + 'ref': st_line.ref, + 'note': st_line.narration or "", + 'name': st_line.name, + 'date': format_date(self.env, st_line.date), + 'amount': amount, + 'amount_str': amount_str, # Amount in the statement line currency + 'currency_id': st_line.currency_id.id or statement_currency.id, + 'partner_id': st_line.partner_id.id, + 'journal_id': st_line.journal_id.id, + 'statement_id': st_line.statement_id.id, + 'account_id': [st_line.journal_id.default_account_id.id, st_line.journal_id.default_account_id.display_name], + 'account_code': st_line.journal_id.default_account_id.code, + 'account_name': st_line.journal_id.default_account_id.name, + 'partner_name': st_line.partner_id.name, + 'communication_partner_name': st_line.partner_name, + 'amount_currency_str': amount_currency_str, # Amount in the statement currency + 'amount_currency': amount_currency, # Amount in the statement currency + 'has_no_partner': not st_line.partner_id.id, + 'company_id': st_line.company_id.id, + } + if st_line.partner_id: + data['open_balance_account_id'] = amount > 0 and st_line.partner_id.property_account_receivable_id.id or st_line.partner_id.property_account_payable_id.id + + return data + + @api.model + def _get_move_line_reconciliation_proposition(self, account_id, partner_id=None): + """ Returns two lines whose amount are opposite """ + + Account_move_line = self.env['account.move.line'] + + ir_rules_query = Account_move_line._where_calc([]) + Account_move_line._apply_ir_rules(ir_rules_query, 'read') + from_clause, where_clause, where_clause_params = ir_rules_query.get_sql() + where_str = where_clause and (" WHERE %s" % where_clause) or '' + + # Get pairs + query = """ + SELECT a.id, b.id + FROM account_move_line a, account_move_line b, + account_move move_a, account_move move_b, + account_journal journal_a, account_journal journal_b + WHERE a.id != b.id + AND move_a.id = a.move_id + AND move_a.state = 'posted' + AND move_a.journal_id = journal_a.id + AND move_b.id = b.move_id + AND move_b.journal_id = journal_b.id + AND move_b.state = 'posted' + AND a.amount_residual = -b.amount_residual + AND a.balance != 0.0 + AND b.balance != 0.0 + AND NOT a.reconciled + AND a.account_id = %s + AND (%s IS NULL AND b.account_id = %s) + AND (%s IS NULL AND NOT b.reconciled OR b.id = %s) + AND (%s is NULL OR (a.partner_id = %s AND b.partner_id = %s)) + AND a.id IN (SELECT "account_move_line".id FROM {0}) + AND b.id IN (SELECT "account_move_line".id FROM {0}) + ORDER BY a.date desc + LIMIT 1 + """.format(from_clause + where_str) + move_line_id = self.env.context.get('move_line_id') or None + params = [ + account_id, + move_line_id, account_id, + move_line_id, move_line_id, + partner_id, partner_id, partner_id, + ] + where_clause_params + where_clause_params + self.env.cr.execute(query, params) + + pairs = self.env.cr.fetchall() + + if pairs: + return Account_move_line.browse(pairs[0]) + return Account_move_line + + @api.model + def _process_move_lines(self, move_line_ids, new_mv_line_dicts): + """ Create new move lines from new_mv_line_dicts (if not empty) then call reconcile_partial on self and new move lines + + :param new_mv_line_dicts: list of dicts containing values suitable for account_move_line.create() + """ + if len(move_line_ids) < 1 or len(move_line_ids) + len(new_mv_line_dicts) < 2: + raise UserError(_('A reconciliation must involve at least 2 move lines.')) + + account_move_line = self.env['account.move.line'].browse(move_line_ids) + writeoff_lines = self.env['account.move.line'] + + # Create writeoff move lines + if len(new_mv_line_dicts) > 0: + company_currency = account_move_line[0].account_id.company_id.currency_id + same_currency = False + currencies = list(set([aml.currency_id or company_currency for aml in account_move_line])) + if len(currencies) == 1 and currencies[0] != company_currency: + same_currency = True + # We don't have to convert debit/credit to currency as all values in the reconciliation widget are displayed in company currency + # If all the lines are in the same currency, create writeoff entry with same currency also + for mv_line_dict in new_mv_line_dicts: + if not same_currency: + mv_line_dict['amount_currency'] = False + writeoff_lines += account_move_line._create_writeoff([mv_line_dict]) + + (account_move_line + writeoff_lines).reconcile() + else: + account_move_line.reconcile() + + +class AccountInvoiceLine(models.Model): + _inherit = 'account.move.line' + + def _create_writeoff(self, writeoff_vals): + def compute_writeoff_counterpart_vals(values): + line_values = values.copy() + line_values['debit'], line_values['credit'] = line_values['credit'], line_values['debit'] + if 'amount_currency' in values: + line_values['amount_currency'] = -line_values['amount_currency'] + return line_values + # Group writeoff_vals by journals + writeoff_dict = {} + for val in writeoff_vals: + journal_id = val.get('journal_id', False) + if not writeoff_dict.get(journal_id, False): + writeoff_dict[journal_id] = [val] + else: + writeoff_dict[journal_id].append(val) + + partner_id = self.env['res.partner']._find_accounting_partner(self[0].partner_id).id + company_currency = self[0].account_id.company_id.currency_id + writeoff_currency = self[0].account_id.currency_id or company_currency + line_to_reconcile = self.env['account.move.line'] + # Iterate and create one writeoff by journal + writeoff_moves = self.env['account.move'] + for journal_id, lines in writeoff_dict.items(): + total = 0 + total_currency = 0 + writeoff_lines = [] + date = fields.Date.today() + for vals in lines: + # Check and complete vals + if 'account_id' not in vals or 'journal_id' not in vals: + raise UserError(_("It is mandatory to specify an account and a journal to create a write-off.")) + if ('debit' in vals) ^ ('credit' in vals): + raise UserError(_("Either pass both debit and credit or none.")) + if 'date' not in vals: + vals['date'] = self._context.get('date_p') or fields.Date.today() + vals['date'] = fields.Date.to_date(vals['date']) + if vals['date'] and vals['date'] < date: + date = vals['date'] + if 'name' not in vals: + vals['name'] = self._context.get('comment') or _('Write-Off') + if 'analytic_account_id' not in vals: + vals['analytic_account_id'] = self.env.context.get('analytic_id', False) + #compute the writeoff amount if not given + if 'credit' not in vals and 'debit' not in vals: + amount = sum([r.amount_residual for r in self]) + vals['credit'] = amount > 0 and amount or 0.0 + vals['debit'] = amount < 0 and abs(amount) or 0.0 + vals['partner_id'] = partner_id + total += vals['debit']-vals['credit'] + if 'amount_currency' not in vals and writeoff_currency != company_currency: + vals['currency_id'] = writeoff_currency.id + sign = 1 if vals['debit'] > 0 else -1 + vals['amount_currency'] = sign * abs(sum([r.amount_residual_currency for r in self])) + total_currency += vals['amount_currency'] + + writeoff_lines.append(compute_writeoff_counterpart_vals(vals)) + + # Create balance line + writeoff_lines.append({ + 'name': _('Write-Off'), + 'debit': total > 0 and total or 0.0, + 'credit': total < 0 and -total or 0.0, + 'amount_currency': total_currency, + 'currency_id': total_currency and writeoff_currency.id or False, + 'journal_id': journal_id, + 'account_id': self[0].account_id.id, + 'partner_id': partner_id + }) + + # Create the move + writeoff_move = self.env['account.move'].create({ + 'journal_id': journal_id, + 'date': date, + 'state': 'draft', + 'line_ids': [(0, 0, line) for line in writeoff_lines], + }) + writeoff_moves += writeoff_move + line_to_reconcile += writeoff_move.line_ids.filtered(lambda r: r.account_id == self[0].account_id).sorted(key='id')[-1:] + + #post all the writeoff moves at once + if writeoff_moves: + writeoff_moves.action_post() + + # Return the writeoff move.line which is to be reconciled + return line_to_reconcile + diff --git a/base_accounting_kit/static/description/banner.gif b/base_accounting_kit/static/description/banner.gif index c1fc695815b0949dd02610a2f0f641a5c193ffb0..58e686ce896101d1770385a88983a7e13771eda5 100644 GIT binary patch literal 114270 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 >~mJyeOAkK7)dXBZv6h>h}^)@LZ_J*Qbc zTil{v-MUQczMS8?-1~RFGsUp)b0w~MwG@4|Rec57e>HV=g$8}Sz;w+da*btoodtdU z<|8+~c@05)qYnCSln2iLsCoZS8(ZUl3=4Wlh5xd#-w`K-YCjDNcmW#SkyzhLP;lApQO<3M;dfzJD0+ht$Ok-|1X)(Jbe+L-CvH* zs13MCTEzRQJbqf(T%2R*$-J3 zYPn>qtAuJd4<4o&o52+Ohmon9Yf+d>adA4;HJ?%|laM7-U(NZYre*Pq zI!N`*heJC|v)rQ@Ot)GQE-YmoRR_W=ENBa-+pWUC3NHyRfl4+>(PCVq!?L4N@4WUmaLo^Vuy;B$6||=&qiKF$^4Ko$;e`Lb_j8L zO1toI!d-CY0ee*l6uV4rHg*Yb-prH1uGThjy`8XUhQ@F_N5uscx~&mkZYmv8v_)y| z__sVb%eiw@x=Uio>Q|*J>r5@5k`&2bP4MKHv`WKt=#M$*=J%!W`B&)ub-+wyEgjxsE7_af(jZtKm654v#+x;oaHhE83yj{_2Y zif?~^|NXRK4dWbJ^t19u>@LO+)sdF=$K7!%JgC@=1#{j%Rg-*Jnk1R&eu6<_r;1*A zJ1PvVf=6XGp735cnMRQKbU^@j;&XWSPU@cCNwnWDJaRVJ7F4+DM?ZrT3`3%g+A}6% zL)ae(r@~c&%@qp$Z2wwLbd+-7drH}YPlLKZB`36 z4CKPvuzvDP$N~g0zrq+5_Qw30i|3ZXu2}|sm|cGWG<4ABES0H90kX5k;M`vpMAryo zd;KQSxG&%0KIypGB&$7tO%Gf?a0|4ONm=F658)Xw51jOIM>&ro*e6?cX@7E-fZ`4k zNo5Wno?vCxM;%>?ZV6qOBx$LdWpw#ba%s8}nC?(2tp_7}Sc>8&OhItMW4y+a>A;9P z&R?l36UFQ;qmy=@k+mI^63$_%DaZ8t%oEuX?&Z-bm-hRto5&L0W2tG6wfpRsi4y+j zQSh|S+kFlMYN;T+^o&3LLoR|`sW8sijF=fLnW}ZEC?c!q!K-6FZkDu|f-;H=d%*^E*S2hWrGoOBU-Y zwGLIpG;S$^(d`T9R|tt65gcYH$}u%Kh}SgYnAW~N9*mZNP9D25<<)rv|NXF}|p z1Ndsbj7RlTwfJvK}J99 ziHkk%w$q|mLw)JXKD&fm%*TsOAvYV2_7&J>Pq z@G;q8*X0J{NK`YDp;#qLh>ZuHngpC{o0#>+tY(zOee|IVRN{?7sb|Fh!)>k)ki zBi_DQZH)YX*l|kInNkhKpLQJSTH6Tge}V-8NQD1ka};oW+HqrvmSWiu(f@U)KiM3H z?EkUjH2it;#3w)59IFi$^TB_|nyYleFbB*3W5;cF&~2Y>j=LIYmbyVB6UlN~Z}*3G z2m^VVKiM3y!*)4t$!G)B1kdVoEN*1fA-jPn*?80o33ikfPDZ+`#U z>a4H!_kgFf<_c1+^%;4juE6qIU#Y+rn~|{e5h|;(nIg+xtjq@M?0C>do9ndW*@>yO ztYRzPrN43us<+zt8m_pLlB=Dk%cA?Iy4fk~uBq@wC-1!D){9)V_%^HWaj~}BubTe? z%8JY*mAHHP#{_@$^^kc>T3$VS~0b(;FcnhhB21y>^ssTlRKJqHO=&mpw+` zEm_`rFOAYD&?E-UD1r}8IAwb;+xKUHH~!e;kiRV}5@wE=+wH95j+E|u?aVs>z8?p?@N*Hr7stn6lss}7 z=*T>3&cF3QAJJQsx^}Ave?3syzr_dl(Ic@Q64sBeUiod=fj;k|bgtbYqO|XRRq)3@ zzvlW_0ex1W5B=@WQT_Xh{EqiM`h-t>2Sil@y|TdAiQ*gm`9}T>7(q%+kSi6`oZtFm zkN0$tC?D*~Ci?I{PpJ<<>>JSuXOqIMtgwY!nj3=TP(T^Z&?hzA3Jd>n$e0&G=z$#k zA%B9%lpzukD)6`vJbIW!C9;HxOWEEK*=58C#n6XVydoBp!T=|-YlIOhp`XIok})Pl zek^2{C{DCNFtTwnZoCN`%q;31d%B6M{$r^_{N;;wkyVGzv=0HWsXR%FqHP#1 zrd$20Kvp`z}3W4X^stA~iKP&0S!yKHqR{dLj73g7R{}P_b%%_$u6H zju)EWj2?a0gVq7Z^jPpbFoF}@U%HBC8v;h~g=NZ3C`7n>-=wZ@(A!|y;xfbg?Orvf zX;$AbIK1wCFexb#V-$bWueBlVDX*(qU20gy>iscvggj*N@|2tL-7vf43FOc)S-vNI zuaSF<~$Yhq@yjIV}u ztZluEQOtTKQR{SRiCt`q=F!i8R<^G<*=(RmWN4$1Hl|}&ZDSKs(EyB!x{tT*Z|=fm zD0>Gy9y<+qyhCO*6Su9&U2bcS(bdV`twz}0?t&X!p8W1NhV!`VgnNYG2akBcd8crH zGf~609tp%H&T)iOyy6STq5wR8uy$>{<0${ z*Jjb79(5#B{hc)wK+~Pxk~7Qv%x6b?3a`#~msr~1mX5pJCrJ0Y+g;g!m$cVE2==hA z{3C%+yo(2)K(!B>$UafLvi1JV1Y$eVZbpgZ^G^9u_V4OgH_GPC-ucSI5A@WQ%IH5{ zdedjmlsNBtQC9Ew)>j>KLKn5{kJ7zepsZ^$cKttYmpg(GA7SNl{NtM&lR+y4uv?;M zHg`W-k~n`F=4G5vs^75eDL?j~eu@9{69Rq4cyb!4-<9#L-w=3c|0mo>KJhMZ_``!_ z{5H*qrUNd7bp-S=n<)O zZ!q{+1OYlrgn`{RItPe={8JF&k%AwQN}wYO$wh=(!G!Z-gsH}XQ(+JukpW!Dg=+IN zU84_O=!GAlHOU1JVTc4{$bcW%gasjl;k1MLV1@#LhF+tFV+eFRNQeJmhjX}w8?lCW zXb+F|4jB+QA0Y}T^H^wDgB|~&h=f>&L~|aPbA(u!g-V!f6F50OMPfSmh=V3GnHX}z z$9_S`5pf8LN)=9e$Pt_B`gqR@;&sEi8HjL(=6)|e33=x@#VhN`#_4ETx(;fOtwH^JC~ z!#EJd$Xej|fy;;x*;s-E;e#=liyaY<2QiQOsD-z85GS}19{7G9xQoSsj{ByL>nITI zXb{Lqf>o9f^H_lpg^Ci9jS(r2|9B8Jn2`lxGafk*(}0M~5jIe8gi>Y}{7Z#ENup7aigxQ$=wiKPgQ7N`+rd6t~@jBhE8 zacOa&qfGYTmbnNzspEcn$%JSWkmr~)E{A!UM?-08ac0Sq$CpYZDU{tvigL&i9ykzo zanQBRVnCXg|SrB>25j7c_`VfsAAvGG2N;ET*tQk&^nUxwd0)?4v5$HOj2z3AO znDK{3@8E`M*@ip_nrnEJ0m+-biIkF=5ylyuzX_NGL7K}c5|wG0IHNJJ$AXX-D2Yjm zq?wJQ`4O?0oNWJjiqd$LYV)02c$?gZo*faMo7oX)M4Idw5=Yq(200`TgOa?a7ArZC z;#r!{37+bSm6QpN7Ab)7DWJ_sgbA9S3;Kx#3RI~XpyL@$)u}N0$$ENnn?cE#6DpD) z(Ng}&oYZ-s49b%sI-n;Cq8=fl9r~dH0i8Vgnh|QD&hap_Nt?B)oya+&@t2CH*`L4( zp9ZQCP*@P!2c#QuP0y&LfBB$mDUcK@hRJA%fmo#RQ7{jXqd1nGbHbtjnTl@m96Y%6h72e&)|CUZ-- zXlu7>OC$o2w=-9_d|R|PG6G<0m|Z!z9AYC6aJV`eeu~>6DDt;$i=D+9xj_3Njr(@p zgSkj@A(YE=!RNU`f*?@90F|4Nom(2?mwh=)x>HCW0)V<@H@c>wfb9yq9`r4Mdvv6C z8kLEy#G!@-mK_4X2fgdNzYDw&p{}p-Gs#uFzX1ivo4QVGyRb2x|4_50;hqsx8;1Xz zyj!PoJK7mNID?!eys_cE2lM~}U>Q)*xZ*p$Vat54VVY%X5U<-A?7KfKv! z?#mVrzyJaa!1OD1T{ax}s}U__j*!TR4cne$IEZH$h9coJlG=#2c)=L~hBL{9sg#EY zR9XNWzyizweDDAxFarPZz6SBWFZ=*}fWQf?zzf{7a7P>u%!?n`i@P{lK$fptXsI2` zn6GHD5_!Tq{KRM5!#<3qKumz-h!BqWfC>SuL@JJ|I(*0Ikr4#NWX!`-TpT~F4=r_> z4goq5v6$<+5LsN0Zz#r2T*i2exLnH{KipJC6OzmrI1<5t-P(y8$;2Azzj^<>$fI^0 z=L>`N8JbiHs1zHe09lkrIg%O?$t29HhYW^CIfG-o$Ycy_-!Yw8K|doh(V3`m3NlI?B!cqeTfRyUTm--+{F8X zWF5WKiJQ+@`crmuuMNS)#LN&+xUU1z%msVViR{u~J=bEFA3vh@iQv=E$n)ED&y8uC6$15oFk-w S-sqj)>b>6V-QHLc5CA*5XY~~T literal 109768 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 K-#_<&0027*AE$Bv diff --git a/base_accounting_kit/static/description/index.html b/base_accounting_kit/static/description/index.html index dce19d6c2..501809481 100644 --- a/base_accounting_kit/static/description/index.html +++ b/base_accounting_kit/static/description/index.html @@ -9,6 +9,21 @@ style="margin:75px 0;position: relative;color: #000;background-position: center;background: #ffffff;border-bottom: 1px solid #e4e4e4; padding-bottom: 30px;">

Latest Updates

+
    +
  • + + Reconciliation Widget Added +
  • +
  • + + Payments Matching   option in Journal Overview +
  • +
  • + + Payments Matching   button Payment Form +
  • +
  • +

Odoo 14 Accounting

Dashboard, Asset Management, Accounting diff --git a/base_accounting_kit/static/src/js/payment_matching.js b/base_accounting_kit/static/src/js/payment_matching.js new file mode 100644 index 000000000..80a173298 --- /dev/null +++ b/base_accounting_kit/static/src/js/payment_matching.js @@ -0,0 +1,505 @@ +odoo.define('base_accounting_kit.ReconciliationClientAction', function (require) { +"use strict"; + +var AbstractAction = require('web.AbstractAction'); +var ReconciliationModel = require('base_accounting_kit.ReconciliationModel'); +var ReconciliationRenderer = require('base_accounting_kit.ReconciliationRenderer'); +var core = require('web.core'); +var QWeb = core.qweb; + + +/** + * Widget used as action for 'account.bank.statement' reconciliation + */ +var StatementAction = AbstractAction.extend({ + hasControlPanel: true, + withSearchBar: true, + loadControlPanel: true, + title: core._t('Bank Reconciliation'), + contentTemplate: 'reconciliation', + custom_events: { + change_mode: '_onAction', + change_filter: '_onAction', + change_offset: '_onAction', + change_partner: '_onAction', + add_proposition: '_onAction', + remove_proposition: '_onAction', + update_proposition: '_onAction', + create_proposition: '_onAction', + getPartialAmount: '_onActionPartialAmount', + quick_create_proposition: '_onAction', + partial_reconcile: '_onAction', + validate: '_onValidate', + close_statement: '_onCloseStatement', + load_more: '_onLoadMore', + reload: 'reload', + search: '_onSearch', + navigation_move:'_onNavigationMove', + }, + config: _.extend({}, AbstractAction.prototype.config, { + // used to instantiate the model + Model: ReconciliationModel.StatementModel, + // used to instantiate the action interface + ActionRenderer: ReconciliationRenderer.StatementRenderer, + // used to instantiate each widget line + LineRenderer: ReconciliationRenderer.LineRenderer, + // used context params + params: ['statement_line_ids'], + // number of statements/partners/accounts to display + defaultDisplayQty: 10, + // number of moves lines displayed in 'match' mode + limitMoveLines: 15, + }), + + _onNavigationMove: function (ev) { + var non_reconciled_keys = _.keys(_.pick(this.model.lines, function(value, key, object) {return !value.reconciled})); + var currentIndex = _.indexOf(non_reconciled_keys, ev.data.handle); + var widget = false; + switch (ev.data.direction) { + case 'up': + ev.stopPropagation(); + widget = this._getWidget(non_reconciled_keys[currentIndex-1]); + break; + case 'down': + ev.stopPropagation(); + widget = this._getWidget(non_reconciled_keys[currentIndex+1]); + break; + case 'validate': + ev.stopPropagation(); + widget = this._getWidget(non_reconciled_keys[currentIndex]); + widget.$('caption .o_buttons button:visible').click(); + break; + } + if (widget) widget.$el.focus(); + }, + + /** + * @override + * @param {Object} params + * @param {Object} params.context + * + */ + init: function (parent, params) { + this._super.apply(this, arguments); + this.action_manager = parent; + this.params = params; + this.searchModelConfig.modelName = 'account.bank.statement.line'; + this.controlPanelProps.cp_content = {}; +// this.controlPanelParams.modelName = 'account.bank.statement.line'; + this.model = new this.config.Model(this, { + modelName: "account.reconciliation.widget", + defaultDisplayQty: params.params && params.params.defaultDisplayQty || this.config.defaultDisplayQty, + limitMoveLines: params.params && params.params.limitMoveLines || this.config.limitMoveLines, + }); + this.widgets = []; + // Adding values from the context is necessary to put this information in the url via the action manager so that + // you can retrieve it if the person shares his url or presses f5 + _.each(params.params, function (value, name) { + params.context[name] = name.indexOf('_ids') !== -1 ? _.map((value+'').split(','), parseFloat) : value; + }); + params.params = {}; + _.each(this.config.params, function (name) { + if (params.context[name]) { + params.params[name] = params.context[name]; + } + }); + }, + + /** + * instantiate the action renderer + * + * @override + */ + willStart: function () { + var self = this; + var def = this.model.load(this.params.context).then(this._super.bind(this)); + return def.then(function () { + if (!self.model.context || !self.model.context.active_id) { + self.model.context = {'active_id': self.params.context.active_id, + 'active_model': self.params.context.active_model}; + } + var journal_id = self.params.context.journal_id; + if (self.model.context.active_id && self.model.context.active_model === 'account.journal') { + journal_id = journal_id || self.model.context.active_id; + } + if (journal_id) { + var promise = self._rpc({ + model: 'account.journal', + method: 'read', + args: [journal_id, ['display_name']], + }); + } else { + var promise = Promise.resolve(); + } + return promise.then(function (result) { + var title = result && result[0] ? result[0]['display_name'] : self.params.display_name || '' + self._setTitle(title); + self.renderer = new self.config.ActionRenderer(self, self.model, { + 'bank_statement_line_id': self.model.bank_statement_line_id, + 'valuenow': self.model.valuenow, + 'valuemax': self.model.valuemax, + 'defaultDisplayQty': self.model.defaultDisplayQty, + 'title': title, + }); + }); + }); + }, + + reload: function() { + // On reload destroy all rendered line widget, reload data and then rerender widget + var self = this; + + self.$('.o_reconciliation_lines').addClass('d-none'); // prevent the browser from recomputing css after each destroy for HUGE perf improvement on a lot of lines + _.each(this.widgets, function(widget) { + widget.destroy(); + }); + this.widgets = []; + self.$('.o_reconciliation_lines').removeClass('d-none'); + return this.model.reload().then(function() { + return self._renderLinesOrRainbow(); + }); + }, + + _renderLinesOrRainbow: function() { + var self = this; + return self._renderLines().then(function() { + var initialState = self.renderer._initialState; + var valuenow = self.model.statement ? self.model.statement.value_min : initialState.valuenow; + var valuemax = self.model.statement ? self.model.statement.value_max : initialState.valuemax; + // No more lines to reconcile, trigger the rainbowman. + if(valuenow === valuemax){ + initialState.valuenow = valuenow; + initialState.context = self.model.getContext(); + self.renderer.showRainbowMan(initialState); + self.remove_cp(); + }else{ + // Create a notification if some lines have been reconciled automatically. + if(initialState.valuenow > 0) + self.renderer._renderNotifications(self.model.statement.notifications); + self._openFirstLine(); + self.renderer.$('[data-toggle="tooltip"]').tooltip(); + self.do_show(); + } + }); + }, + + /** + * append the renderer and instantiate the line renderers + * + * @override + */ + start: function () { + var self = this; + var args = arguments; + var sup = this._super; + + return this.renderer.prependTo(self.$('.o_form_sheet')).then(function() { + return self._renderLinesOrRainbow().then(function() { + self.do_show(); + return sup.apply(self, args); + }); + }); + }, + + /** + * update the control panel and breadcrumbs + * + * @override + */ + do_show: function () { + this._super.apply(this, arguments); + if (this.action_manager) { + this.$pager = $(QWeb.render('reconciliation.control.pager', {widget: this.renderer})); + this.controlPanelProps.cp_content = {$pager: this.$pager}; +// this.updateControlPanel({ +// clear: true, +// cp_content: { +// $pager: this.$pager, +// }, +// }); + this.renderer.$progress = this.$pager; + $(this.renderer.$progress).parent().css('width', '100%').css('padding-left', '0'); + } + }, + + remove_cp: function() { + this.controlPanelProps.cp_content = {}; +// this.updateControlPanel({ +// clear: true, +// }); + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @private + * @param {string} handle + * @returns {Widget} widget line + */ + _getWidget: function (handle) { + return _.find(this.widgets, function (widget) {return widget.handle===handle;}); + }, + + /** + * + */ + _loadMore: function(qty) { + var self = this; + return this.model.loadMore(qty).then(function () { + return self._renderLines(); + }); + }, + /** + * sitch to 'match' the first available line + * + * @private + */ + _openFirstLine: function (previous_handle) { + var self = this; + previous_handle = previous_handle || 'rline0'; + var handle = _.compact(_.map(this.model.lines, function (line, handle) { + return (line.reconciled || (parseInt(handle.substr(5)) < parseInt(previous_handle.substr(5)))) ? null : handle; + }))[0]; + if (handle) { + var line = this.model.getLine(handle); + this.model.changeMode(handle, 'default').then(function () { + self._getWidget(handle).update(line); + }).guardedCatch(function(){ + self._getWidget(handle).update(line); + }).then(function() { + self._getWidget(handle).$el.focus(); + } + ); + } + return handle; + }, + + _forceUpdate: function() { + var self = this; + _.each(this.model.lines, function(handle) { + var widget = self._getWidget(handle['handle']); + if (widget && handle.need_update) { + widget.update(handle); + widget.need_update = false; + } + }) + }, + /** + * render line widget and append to view + * + * @private + */ + _renderLines: function () { + var self = this; + var linesToDisplay = this.model.getStatementLines(); + var linePromises = []; + _.each(linesToDisplay, function (line, handle) { + var widget = new self.config.LineRenderer(self, self.model, line); + widget.handle = handle; + self.widgets.push(widget); + linePromises.push(widget.appendTo(self.$('.o_reconciliation_lines'))); + }); + if (this.model.hasMoreLines() === false) { + this.renderer.hideLoadMoreButton(true); + } + else { + this.renderer.hideLoadMoreButton(false); + } + return Promise.all(linePromises); + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * dispatch on the camelcased event name to model method then update the + * line renderer with the new state. If the mode was switched from 'inactive' + * to 'create' or 'match_rp' or 'match_other', the other lines switch to + * 'inactive' mode + * + * @private + * @param {OdooEvent} event + */ + _onAction: function (event) { + var self = this; + var handle = event.target.handle; + var current_line = this.model.getLine(handle); + this.model[_.str.camelize(event.name)](handle, event.data.data).then(function () { + var widget = self._getWidget(handle); + if (widget) { + widget.update(current_line); + } + if (current_line.mode !== 'inactive') { + _.each(self.model.lines, function (line, _handle) { + if (line.mode !== 'inactive' && _handle !== handle) { + self.model.changeMode(_handle, 'inactive'); + var widget = self._getWidget(_handle); + if (widget) { + widget.update(line); + } + } + }); + } + }); + }, + + /** + * @private + * @param {OdooEvent} ev + */ + _onSearch: function (ev) { + var self = this; + ev.stopPropagation(); + this.model.domain = ev.data.domain; + this.model.display_context = 'search'; + self.reload().then(function() { + self.renderer._updateProgressBar({ + 'valuenow': self.model.valuenow, + 'valuemax': self.model.valuemax, + }); + }); + }, + + _onActionPartialAmount: function(event) { + var self = this; + var handle = event.target.handle; + var line = this.model.getLine(handle); + var amount = this.model.getPartialReconcileAmount(handle, event.data); + self._getWidget(handle).updatePartialAmount(event.data.data, amount); + }, + + /** + * call 'closeStatement' model method + * + * @private + * @param {OdooEvent} event + */ + _onCloseStatement: function (event) { + var self = this; + return this.model.closeStatement().then(function (result) { + self.do_action({ + name: 'Bank Statements', + res_model: 'account.bank.statement.line', + res_id: result, + views: [[false, 'form']], + type: 'ir.actions.act_window', + view_mode: 'form', + }); + $('.o_reward').remove(); + }); + }, + /** + * Load more statement and render them + * + * @param {OdooEvent} event + */ + _onLoadMore: function (event) { + return this._loadMore(this.model.defaultDisplayQty); + }, + /** + * call 'validate' model method then destroy the + * validated lines and update the action renderer with the new status bar + * values and notifications then open the first available line + * + * @private + * @param {OdooEvent} event + */ + _onValidate: function (event) { + var self = this; + var handle = event.target.handle; + this.model.validate(handle).then(function (result) { + self.renderer.update({ + 'valuenow': self.model.valuenow, + 'valuemax': self.model.valuemax, + 'title': self.title, + 'time': Date.now()-self.time, + 'notifications': result.notifications, + 'context': self.model.getContext(), + }); + self._forceUpdate(); + _.each(result.handles, function (handle) { + var widget = self._getWidget(handle); + if (widget) { + widget.destroy(); + var index = _.findIndex(self.widgets, function (widget) {return widget.handle===handle;}); + self.widgets.splice(index, 1); + } + }); + // Get number of widget and if less than constant and if there are more to laod, load until constant + if (self.widgets.length < self.model.defaultDisplayQty + && self.model.valuemax - self.model.valuenow >= self.model.defaultDisplayQty) { + var toLoad = self.model.defaultDisplayQty - self.widgets.length; + self._loadMore(toLoad); + } + self._openFirstLine(handle); + }); + }, +}); + + +/** + * Widget used as action for 'account.move.line' and 'res.partner' for the + * manual reconciliation and mark data as reconciliate + */ +var ManualAction = StatementAction.extend({ + title: core._t('Journal Items to Reconcile'), + withSearchBar: false, + config: _.extend({}, StatementAction.prototype.config, { + Model: ReconciliationModel.ManualModel, + ActionRenderer: ReconciliationRenderer.ManualRenderer, + LineRenderer: ReconciliationRenderer.ManualLineRenderer, + params: ['company_ids', 'mode', 'partner_ids', 'account_ids'], + defaultDisplayQty: 30, + limitMoveLines: 15, + }), + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * call 'validate' model method then destroy the + * reconcilied lines, update the not reconcilied and update the action + * renderer with the new status bar values and notifications then open the + * first available line + * + * @private + * @param {OdooEvent} event + */ + _onValidate: function (event) { + var self = this; + var handle = event.target.handle; + var method = 'validate'; + this.model[method](handle).then(function (result) { + _.each(result.reconciled, function (handle) { + self._getWidget(handle).destroy(); + }); + _.each(result.updated, function (handle) { + self._getWidget(handle).update(self.model.getLine(handle)); + }); + self.renderer.update({ + valuenow: _.compact(_.invoke(self.widgets, 'isDestroyed')).length, + valuemax: self.widgets.length, + title: self.title, + time: Date.now()-self.time, + }); + if(!_.any(result.updated, function (handle) { + return self.model.getLine(handle).mode !== 'inactive'; + })) { + self._openFirstLine(handle); + } + }); + }, +}); + +core.action_registry.add('bank_statement_reconciliation_view', StatementAction); +core.action_registry.add('manual_reconciliation_view', ManualAction); + +return { + StatementAction: StatementAction, + ManualAction: ManualAction, +}; +}); diff --git a/base_accounting_kit/static/src/js/payment_model.js b/base_accounting_kit/static/src/js/payment_model.js new file mode 100644 index 000000000..07785c4b2 --- /dev/null +++ b/base_accounting_kit/static/src/js/payment_model.js @@ -0,0 +1,1881 @@ +odoo.define('base_accounting_kit.ReconciliationModel', function (require) { +"use strict"; + +var BasicModel = require('web.BasicModel'); +var field_utils = require('web.field_utils'); +var utils = require('web.utils'); +var session = require('web.session'); +var WarningDialog = require('web.CrashManager').WarningDialog; +var core = require('web.core'); +var _t = core._t; + + +/** + * Model use to fetch, format and update 'account.reconciliation.widget', + * datas allowing reconciliation + * + * The statement internal structure:: + * + * { + * valuenow: integer + * valuenow: valuemax + * [bank_statement_line_id]: { + * id: integer + * display_name: string + * } + * reconcileModels: [object] + * accounts: {id: code} + * } + * + * The internal structure of each line is:: + * + * { + * balance: { + * type: number - show/hide action button + * amount: number - real amount + * amount_str: string - formated amount + * account_code: string + * }, + * st_line: { + * partner_id: integer + * partner_name: string + * } + * mode: string ('inactive', 'match_rp', 'match_other', 'create') + * reconciliation_proposition: { + * id: number|string + * partial_amount: number + * invalid: boolean - through the invalid line (without account, label...) + * account_code: string + * date: string + * date_maturity: string + * label: string + * amount: number - real amount + * amount_str: string - formated amount + * [already_paid]: boolean + * [partner_id]: integer + * [partner_name]: string + * [account_code]: string + * [journal_id]: { + * id: integer + * display_name: string + * } + * [ref]: string + * [is_partially_reconciled]: boolean + * [to_check]: boolean + * [amount_currency_str]: string|false (amount in record currency) + * } + * mv_lines_match_rp: object - idem than reconciliation_proposition + * mv_lines_match_other: object - idem than reconciliation_proposition + * limitMoveLines: integer + * filter: string + * [createForm]: { + * account_id: { + * id: integer + * display_name: string + * } + * tax_ids: { + * id: integer + * display_name: string + * } + * analytic_account_id: { + * id: integer + * display_name: string + * } + * analytic_tag_ids: { + * } + * label: string + * amount: number, + * [journal_id]: { + * id: integer + * display_name: string + * } + * } + * } + */ +var StatementModel = BasicModel.extend({ + avoidCreate: false, + quickCreateFields: ['account_id', 'amount', 'analytic_account_id', 'label', 'tax_ids', 'force_tax_included', 'analytic_tag_ids', 'to_check'], + + // overridden in ManualModel + modes: ['create', 'match_rp', 'match_other'], + + /** + * @override + * + * @param {Widget} parent + * @param {object} options + */ + init: function (parent, options) { + this._super.apply(this, arguments); + this.reconcileModels = []; + this.lines = {}; + this.valuenow = 0; + this.valuemax = 0; + this.alreadyDisplayed = []; + this.domain = []; + this.defaultDisplayQty = options && options.defaultDisplayQty || 10; + this.limitMoveLines = options && options.limitMoveLines || 15; + this.display_context = 'init'; + }, + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * add a reconciliation proposition from the matched lines + * We also display a warning if the user tries to add 2 line with different + * account type + * + * @param {string} handle + * @param {number} mv_line_id + * @returns {Promise} + */ + addProposition: function (handle, mv_line_id) { + var self = this; + var line = this.getLine(handle); + var prop = _.clone(_.find(line['mv_lines_'+line.mode], {'id': mv_line_id})); + this._addProposition(line, prop); + line['mv_lines_'+line.mode] = _.filter(line['mv_lines_'+line.mode], l => l['id'] != mv_line_id); + + // remove all non valid lines + line.reconciliation_proposition = _.filter(line.reconciliation_proposition, function (prop) {return prop && !prop.invalid;}); + + // Onchange the partner if not already set on the statement line. + if(!line.st_line.partner_id && line.reconciliation_proposition + && line.reconciliation_proposition.length == 1 && prop.partner_id && line.type === undefined){ + return this.changePartner(handle, {'id': prop.partner_id, 'display_name': prop.partner_name}, true); + } + + return Promise.all([ + this._computeLine(line), + this._performMoveLine(handle, 'match_rp', line.mode == 'match_rp'? 1 : 0), + this._performMoveLine(handle, 'match_other', line.mode == 'match_other'? 1 : 0) + ]); + }, + /** + * change the filter for the target line and fetch the new matched lines + * + * @param {string} handle + * @param {string} filter + * @returns {Promise} + */ + changeFilter: function (handle, filter) { + var line = this.getLine(handle); + line['filter_'+line.mode] = filter; + line['mv_lines_'+line.mode] = []; + return this._performMoveLine(handle, line.mode); + }, + /** + * change the mode line ('inactive', 'match_rp', 'match_other', 'create'), + * and fetch the new matched lines or prepare to create a new line + * + * ``match_rp`` + * display the matched lines from receivable/payable accounts, the user + * can select the lines to apply there as proposition + * ``match_other`` + * display the other matched lines, the user can select the lines to apply + * there as proposition + * ``create`` + * display fields and quick create button to create a new proposition + * for the reconciliation + * + * @param {string} handle + * @param {'inactive' | 'match_rp' | 'create'} mode + * @returns {Promise} + */ + changeMode: function (handle, mode) { + var self = this; + var line = this.getLine(handle); + if (mode === 'default') { + var match_requests = self.modes.filter(x => x.startsWith('match')).map(x => this._performMoveLine(handle, x)) + return Promise.all(match_requests).then(function() { + return self.changeMode(handle, self._getDefaultMode(handle)); + }); + } + if (mode === 'next') { + var available_modes = self._getAvailableModes(handle) + mode = available_modes[(available_modes.indexOf(line.mode) + 1) % available_modes.length]; + } + line.mode = mode; + if (['match_rp', 'match_other'].includes(line.mode)) { + if (!(line['mv_lines_' + line.mode] && line['mv_lines_' + line.mode].length)) { + return this._performMoveLine(handle, line.mode); + } else { + return this._formatMoveLine(handle, line.mode, []); + } + } + if (line.mode === 'create') { + return this.createProposition(handle); + } + return Promise.resolve(); + }, + /** + * fetch the more matched lines + * + * @param {string} handle + * @returns {Promise} + */ + changeOffset: function (handle) { + var line = this.getLine(handle); + return this._performMoveLine(handle, line.mode); + }, + /** + * change the partner on the line and fetch the new matched lines + * + * @param {string} handle + * @param {bool} preserveMode + * @param {Object} partner + * @param {string} partner.display_name + * @param {number} partner.id + * @returns {Promise} + */ + changePartner: function (handle, partner, preserveMode) { + var self = this; + var line = this.getLine(handle); + line.st_line.partner_id = partner && partner.id; + line.st_line.partner_name = partner && partner.display_name || ''; + line.mv_lines_match_rp = []; + line.mv_lines_match_other = []; + return Promise.resolve(partner && this._changePartner(handle, partner.id)) + .then(function() { + if(line.st_line.partner_id){ + _.each(line.reconciliation_proposition, function(prop){ + if(prop.partner_id != line.st_line.partner_id){ + line.reconciliation_proposition = []; + return false; + } + }); + } + return self._computeLine(line); + }) + .then(function () { + return self.changeMode(handle, preserveMode ? line.mode : 'default', true); + }) + + }, + /** + * close the statement + * @returns {Promise} resolves to the res_id of the closed statements + */ + closeStatement: function () { + var self = this; + return this._rpc({ + model: 'account.bank.statement.line', + method: 'button_confirm_bank', + args: [self.bank_statement_line_id.id], + }) + .then(function () { + return self.bank_statement_line_id.id; + }); + }, + /** + * + * then open the first available line + * + * @param {string} handle + * @returns {Promise} + */ + createProposition: function (handle) { + var line = this.getLine(handle); + var prop = _.filter(line.reconciliation_proposition, '__focus'); + prop = this._formatQuickCreate(line); + line.reconciliation_proposition.push(prop); + line.createForm = _.pick(prop, this.quickCreateFields); + return this._computeLine(line); + }, + /** + * Return context information and journal_id + * @returns {Object} context + */ + getContext: function () { + return this.context; + }, + /** + * Return the lines that needs to be displayed by the widget + * + * @returns {Object} lines that are loaded and not yet displayed + */ + getStatementLines: function () { + var self = this; + var linesToDisplay = _.pick(this.lines, function(value, key, object) { + if (value.visible === true && self.alreadyDisplayed.indexOf(key) === -1) { + self.alreadyDisplayed.push(key); + return object; + } + }); + return linesToDisplay; + }, + /** + * Return a boolean telling if load button needs to be displayed or not + * overridden in ManualModel + * + * @returns {boolean} true if load more button needs to be displayed + */ + hasMoreLines: function () { + var notDisplayed = _.filter(this.lines, function(line) { return !line.visible; }); + if (notDisplayed.length > 0) { + return true; + } + return false; + }, + /** + * get the line data for this handle + * + * @param {Object} handle + * @returns {Object} + */ + getLine: function (handle) { + return this.lines[handle]; + }, + /** + * load data from + * + * - 'account.bank.statement' fetch the line id and bank_statement_id info + * - 'account.reconcile.model' fetch all reconcile model (for quick add) + * - 'account.account' fetch all account code + * - 'account.reconciliation.widget' fetch each line data + * + * overridden in ManualModel + * @param {Object} context + * @param {number[]} context.statement_line_ids + * @returns {Promise} + */ + load: function (context) { + var self = this; + this.context = context; + this.statement_line_ids = context.statement_line_ids; + if (this.statement_line_ids === undefined) { + // This could be undefined if the user pressed F5, take everything as fallback instead of rainbowman + return self._rpc({ + model: 'account.bank.statement.line', + method: 'search_read', + fields: ['id'], + domain: [['journal_id', '=?', context.active_id]], + }).then(function (result) { + self.statement_line_ids = result.map(r => r.id); + return self.reload() + }) + } else { + return self.reload(); + } + + }, + /** + * Load more bank statement line + * + * @param {integer} qty quantity to load + * @returns {Promise} + */ + loadMore: function(qty) { + if (qty === undefined) { + qty = this.defaultDisplayQty; + } + var ids = _.pluck(this.lines, 'id'); + ids = ids.splice(this.pagerIndex, qty); + this.pagerIndex += qty; + return this.loadData(ids, this._getExcludedIds()); + }, + /** + * RPC method to load informations on lines + * overridden in ManualModel + * + * @param {Array} ids ids of bank statement line passed to rpc call + * @param {Array} excluded_ids list of move_line ids that needs to be excluded from search + * @returns {Promise} + */ + loadData: function(ids) { + var self = this; + var excluded_ids = this._getExcludedIds(); + return self._rpc({ + model: 'account.reconciliation.widget', + method: 'get_bank_statement_line_data', + args: [ids, excluded_ids], + context: self.context, + }) + .then(function(res){ + return self._formatLine(res['lines']); + }) + }, + /** + * Reload all data + */ + reload: function() { + var self = this; + self.alreadyDisplayed = []; + self.lines = {}; + self.pagerIndex = 0; + var def_statement = this._rpc({ + model: 'account.reconciliation.widget', + method: 'get_bank_statement_data', + kwargs: {"bank_statement_line_ids":self.statement_line_ids, "srch_domain":self.domain}, + context: self.context, + }) + .then(function (statement) { + self.statement = statement; + self.bank_statement_line_id = self.statement_line_ids.length === 1 ? {id: self.statement_line_ids[0], display_name: statement.statement_name} : false; + self.valuenow = self.valuenow || statement.value_min; + self.valuemax = self.valuemax || statement.value_max; + self.context.journal_id = statement.journal_id; + _.each(statement.lines, function (res) { + var handle = _.uniqueId('rline'); + self.lines[handle] = { + id: res.st_line.id, + partner_id: res.st_line.partner_id, + handle: handle, + reconciled: false, + mode: 'inactive', + mv_lines_match_rp: [], + mv_lines_match_other: [], + filter_match_rp: "", + filter_match_other: "", + reconciliation_proposition: [], + reconcileModels: [], + }; + }); + }); + var domainReconcile = []; + if (self.context && self.context.company_ids) { + domainReconcile.push(['company_id', 'in', self.context.company_ids]); + } + if (self.context && self.context.active_model === 'account.journal' && self.context.active_ids) { + domainReconcile.push('|'); + domainReconcile.push(['match_journal_ids', '=', false]); + domainReconcile.push(['match_journal_ids', 'in', self.context.active_ids]); + } + var def_reconcileModel = this._loadReconciliationModel({domainReconcile: domainReconcile}); + var def_account = this._rpc({ + model: 'account.account', + method: 'search_read', + fields: ['code'], + }) + .then(function (accounts) { + self.accounts = _.object(_.pluck(accounts, 'id'), _.pluck(accounts, 'code')); + }); + var def_taxes = self._loadTaxes(); + return Promise.all([def_statement, def_reconcileModel, def_account, def_taxes]).then(function () { + _.each(self.lines, function (line) { + line.reconcileModels = self.reconcileModels; + }); + var ids = _.pluck(self.lines, 'id'); + ids = ids.splice(0, self.defaultDisplayQty); + self.pagerIndex = ids.length; + return self._formatLine(self.statement.lines); + }); + }, + _readAnalyticTags: function (params) { + var self = this; + this.analyticTags = {}; + if (!params || !params.res_ids || !params.res_ids.length) { + return $.when(); + } + var fields = (params && params.fields || []).concat(['id', 'display_name']); + return this._rpc({ + model: 'account.analytic.tag', + method: 'read', + args: [ + params.res_ids, + fields, + ], + }).then(function (tags) { + for (var i=0; i= Math.abs(amount)) { + amount = Math.abs(amount); + } else if (partial <= Math.abs(prop.amount) && partial >= 0) { + amount = partial; + } else { + amount = Math.abs(amount); + } + return field_utils.format.monetary(amount, {}, formatOptions); + } + }, + /** + * Force the partial reconciliation to display the reconciliate button. + * + * @param {string} handle + * @returns {Promise} + */ + partialReconcile: function(handle, data) { + var line = this.getLine(handle); + var prop = _.find(line.reconciliation_proposition, {'id' : data.mvLineId}); + if (prop) { + var amount = data.amount; + try { + amount = field_utils.parse.float(data.amount); + } + catch (err) { + amount = NaN; + } + // Amount can't be greater than line.amount and can not be negative and must be a number + // the amount we receive will be a string, so take sign of previous line amount in consideration in order to put + // the amount in the correct left or right column + if (amount >= Math.abs(prop.amount) || amount <= 0 || isNaN(amount)) { + delete prop.partial_amount_str; + delete prop.partial_amount; + if (isNaN(amount) || amount < 0) { + this.do_warn(_.str.sprintf(_t('The amount %s is not a valid partial amount'), data.amount)); + } + return this._computeLine(line); + } + else { + var format_options = { currency_id: line.st_line.currency_id }; + prop.partial_amount = (prop.amount > 0 ? 1 : -1)*amount; + prop.partial_amount_str = field_utils.format.monetary(Math.abs(prop.partial_amount), {}, format_options); + } + } + return this._computeLine(line); + }, + /** + * Change the value of the editable proposition line or create a new one. + * + * If the editable line comes from a reconcile model with 2 lines + * and their 'amount_type' is "percent" + * and their total equals 100% (this doesn't take into account the taxes + * who can be included or not) + * Then the total is recomputed to have 100%. + * + * @param {string} handle + * @param {*} values + * @returns {Promise} + */ + updateProposition: function (handle, values) { + var self = this; + var line = this.getLine(handle); + var prop = _.last(_.filter(line.reconciliation_proposition, '__focus')); + if ('to_check' in values && values.to_check === false) { + // check if we have another line with to_check and if yes don't change value of this proposition + prop.to_check = line.reconciliation_proposition.some(function(rec_prop, index) { + return rec_prop.id !== prop.id && rec_prop.to_check; + }); + } + if (!prop) { + prop = this._formatQuickCreate(line); + line.reconciliation_proposition.push(prop); + } + _.each(values, function (value, fieldName) { + if (fieldName === 'analytic_tag_ids') { + switch (value.operation) { + case "ADD_M2M": + // handle analytic_tag selection via drop down (single dict) and + // full widget (array of dict) + var vids = _.isArray(value.ids) ? value.ids : [value.ids]; + _.each(vids, function (val) { + if (!_.findWhere(prop.analytic_tag_ids, {id: val.id})) { + prop.analytic_tag_ids.push(val); + } + }); + break; + case "FORGET": + var id = self.localData[value.ids[0]].ref; + prop.analytic_tag_ids = _.filter(prop.analytic_tag_ids, function (val) { + return val.id !== id; + }); + break; + } + } + else if (fieldName === 'tax_ids') { + switch(value.operation) { + case "ADD_M2M": + prop.__tax_to_recompute = true; + var vids = _.isArray(value.ids) ? value.ids : [value.ids]; + _.each(vids, function(val){ + if (!_.findWhere(prop.tax_ids, {id: val.id})) { + value.ids.price_include = self.taxes[val.id] ? self.taxes[val.id].price_include : false; + prop.tax_ids.push(val); + } + }); + break; + case "FORGET": + prop.__tax_to_recompute = true; + var id = self.localData[value.ids[0]].ref; + prop.tax_ids = _.filter(prop.tax_ids, function (val) { + return val.id !== id; + }); + break; + } + } + else { + prop[fieldName] = values[fieldName]; + } + }); + if ('account_id' in values) { + prop.account_code = prop.account_id ? this.accounts[prop.account_id.id] : ''; + } + if ('amount' in values) { + prop.base_amount = values.amount; + if (prop.reconcileModelId) { + this._computeReconcileModels(handle, prop.reconcileModelId); + } + } + if ('force_tax_included' in values || 'amount' in values || 'account_id' in values) { + prop.__tax_to_recompute = true; + } + line.createForm = _.pick(prop, this.quickCreateFields); + // If you check/uncheck the force_tax_included box, reset the createForm amount. + if(prop.base_amount) + line.createForm.amount = prop.base_amount; + if (prop.tax_ids.length !== 1 ) { + // When we have 0 or more than 1 taxes, reset the base_amount and force_tax_included, otherwise weird behavior can happen + prop.amount = prop.base_amount; + line.createForm.force_tax_included = false; + } + return this._computeLine(line); + }, + /** + * Format the value and send it to 'account.reconciliation.widget' model + * Update the number of validated lines + * overridden in ManualModel + * + * @param {(string|string[])} handle + * @returns {Promise} resolved with an object who contains + * 'handles' key + */ + validate: function (handle) { + var self = this; + this.display_context = 'validate'; + var handles = []; + if (handle) { + handles = [handle]; + } else { + _.each(this.lines, function (line, handle) { + if (!line.reconciled && line.balance && !line.balance.amount && line.reconciliation_proposition.length) { + handles.push(handle); + } + }); + } + var ids = []; + var values = []; + var handlesPromises = []; + _.each(handles, function (handle) { + var line = self.getLine(handle); + var props = _.filter(line.reconciliation_proposition, function (prop) {return !prop.invalid;}); + var computeLinePromise; + if (props.length === 0) { + // Usability: if user has not chosen any lines and click validate, it has the same behavior + // as creating a write-off of the same amount. + props.push(self._formatQuickCreate(line, { + account_id: [line.st_line.open_balance_account_id, self.accounts[line.st_line.open_balance_account_id]], + })); + // update balance of line otherwise it won't be to zero and another line will be added + line.reconciliation_proposition.push(props[0]); + computeLinePromise = self._computeLine(line); + } + ids.push(line.id); + handlesPromises.push(Promise.resolve(computeLinePromise).then(function() { + var values_dict = { + "partner_id": line.st_line.partner_id, + "counterpart_aml_dicts": _.map(_.filter(props, function (prop) { + return !isNaN(prop.id) && !prop.already_paid; + }), self._formatToProcessReconciliation.bind(self, line)), + "payment_aml_ids": _.pluck(_.filter(props, function (prop) { + return !isNaN(prop.id) && prop.already_paid; + }), 'id'), + "new_aml_dicts": _.map(_.filter(props, function (prop) { + return isNaN(prop.id) && prop.display; + }), self._formatToProcessReconciliation.bind(self, line)), + "to_check": line.to_check, + }; + + // If the lines are not fully balanced, create an unreconciled amount. + // line.st_line.currency_id is never false here because its equivalent to + // statement_line.currency_id or statement_line.journal_id.currency_id or statement_line.journal_id.company_id.currency_id (Python-side). + // see: get_statement_line_for_reconciliation_widget method in account/models/account_bank_statement.py for more details + var currency = session.get_currency(line.st_line.currency_id); + var balance = line.balance.amount; + if (!utils.float_is_zero(balance, currency.digits[1])) { + var unreconciled_amount_dict = { + 'account_id': line.st_line.open_balance_account_id, + 'credit': balance > 0 ? balance : 0, + 'debit': balance < 0 ? -balance : 0, + 'name': line.st_line.name + ' : ' + _t("Open balance"), + }; + values_dict['new_aml_dicts'].push(unreconciled_amount_dict); + } + values.push(values_dict); + line.reconciled = true; + })); + + _.each(self.lines, function(other_line) { + if (other_line != line) { + var filtered_prop = other_line.reconciliation_proposition.filter(p => !line.reconciliation_proposition.map(l => l.id).includes(p.id)); + if (filtered_prop.length != other_line.reconciliation_proposition.length) { + other_line.need_update = true; + other_line.reconciliation_proposition = filtered_prop; + } + self._computeLine(line); + } + }) + }); + + return Promise.all(handlesPromises).then(function() { + return self._rpc({ + model: 'account.reconciliation.widget', + method: 'process_bank_statement_line', + args: [ids, values], + context: self.context, + }) + .then(self._validatePostProcess.bind(self)) + .then(function () { + self.valuenow += handles.length; + return {handles: handles}; + }); + }); + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * add a line proposition after checking receivable and payable accounts constraint + * + * @private + * @param {Object} line + * @param {Object} prop + */ + _addProposition: function (line, prop) { + line.reconciliation_proposition.push(prop); + }, + /** + * stop the editable proposition line and remove it if it's invalid then + * compute the line + * + * See :func:`_computeLine` + * + * @private + * @param {string} handle + * @returns {Promise} + */ + _blurProposition: function (handle) { + var line = this.getLine(handle); + line.reconciliation_proposition = _.filter(line.reconciliation_proposition, function (l) { + l.__focus = false; + return !l.invalid; + }); + }, + /** + * When changing partner, read property_account_receivable and payable + * of that partner because the counterpart account might cahnge depending + * on the partner + * + * @private + * @param {string} handle + * @param {integer} partner_id + * @returns {Promise} + */ + _changePartner: function (handle, partner_id) { + var self = this; + return this._rpc({ + model: 'res.partner', + method: 'read', + args: [partner_id, ["property_account_receivable_id", "property_account_payable_id"]], + }).then(function (result) { + if (result.length > 0) { + var line = self.getLine(handle); + self.lines[handle].st_line.open_balance_account_id = line.balance.amount < 0 ? result[0]['property_account_payable_id'][0] : result[0]['property_account_receivable_id'][0]; + } + }); + }, + /** + * Calculates the balance; format each proposition amount_str and mark as + * invalid the line with empty account_id, amount or label + * Check the taxes server side for each updated propositions with tax_ids + * extended by ManualModel + * + * @private + * @param {Object} line + * @returns {Promise} + */ + _computeLine: function (line) { + //balance_type + var self = this; + + // compute taxes + var tax_defs = []; + var reconciliation_proposition = []; + var formatOptions = { + currency_id: line.st_line.currency_id, + }; + line.to_check = false; + _.each(line.reconciliation_proposition, function (prop) { + if (prop.to_check) { + // If one of the proposition is to_check, set the global to_check flag to true + line.to_check = true; + } + if (prop.tax_repartition_line_id) { + if (!_.find(line.reconciliation_proposition, {'id': prop.link}).__tax_to_recompute) { + reconciliation_proposition.push(prop); + } + return; + } + if (!prop.already_paid && parseInt(prop.id)) { + prop.is_move_line = true; + } + reconciliation_proposition.push(prop); + + if (prop.tax_ids && prop.tax_ids.length && prop.__tax_to_recompute && prop.base_amount) { + reconciliation_proposition = _.filter(reconciliation_proposition, function (p) { + return !p.tax_repartition_line_id || p.link !== prop.id; + }); + var args = [prop.tax_ids.map(function(el){return el.id;}), prop.base_amount, formatOptions.currency_id]; + var add_context = {'round': true}; + if(prop.tax_ids.length === 1 && line.createForm && line.createForm.force_tax_included) + add_context.force_price_include = true; + tax_defs.push(self._rpc({ + model: 'account.tax', + method: 'json_friendly_compute_all', + args: args, + context: $.extend({}, self.context || {}, add_context), + }) + .then(function (result) { + _.each(result.taxes, function(tax){ + var tax_prop = self._formatQuickCreate(line, { + 'link': prop.id, + 'tax_ids': tax.tax_ids, + 'tax_repartition_line_id': tax.tax_repartition_line_id, + 'tag_ids': tax.tag_ids, + 'amount': tax.amount, + 'label': prop.label ? prop.label + " " + tax.name : tax.name, + 'date': prop.date, + 'account_id': tax.account_id ? [tax.account_id, null] : prop.account_id, + 'analytic': tax.analytic, + '__focus': false + }); + + prop.tax_exigible = tax.tax_exigibility === 'on_payment' ? true : undefined; + prop.amount = tax.base; + prop.amount_str = field_utils.format.monetary(Math.abs(prop.amount), {}, formatOptions); + prop.invalid = !self._isValid(prop); + + tax_prop.amount_str = field_utils.format.monetary(Math.abs(tax_prop.amount), {}, formatOptions); + tax_prop.invalid = prop.invalid; + + reconciliation_proposition.push(tax_prop); + }); + + prop.tag_ids = result.base_tags; + })); + } else { + prop.amount_str = field_utils.format.monetary(Math.abs(prop.amount), {}, formatOptions); + prop.display = self._isDisplayedProposition(prop); + prop.invalid = !self._isValid(prop); + } + }); + + return Promise.all(tax_defs).then(function () { + _.each(reconciliation_proposition, function (prop) { + prop.__tax_to_recompute = false; + }); + line.reconciliation_proposition = reconciliation_proposition; + + var amount_currency = 0; + var total = line.st_line.amount || 0; + var isOtherCurrencyId = _.uniq(_.pluck(_.reject(reconciliation_proposition, 'invalid'), 'currency_id')); + isOtherCurrencyId = isOtherCurrencyId.length === 1 && !total && isOtherCurrencyId[0] !== formatOptions.currency_id ? isOtherCurrencyId[0] : false; + + _.each(reconciliation_proposition, function (prop) { + if (!prop.invalid) { + total -= prop.partial_amount || prop.amount; + if (isOtherCurrencyId) { + amount_currency -= (prop.amount < 0 ? -1 : 1) * Math.abs(prop.amount_currency); + } + } + }); + var company_currency = session.get_currency(line.st_line.currency_id); + var company_precision = company_currency && company_currency.digits[1] || 2; + total = utils.round_decimals(total, company_precision) || 0; + if(isOtherCurrencyId){ + var other_currency = session.get_currency(isOtherCurrencyId); + var other_precision = other_currency && other_currency.digits[1] || 2; + amount_currency = utils.round_decimals(amount_currency, other_precision); + } + line.balance = { + amount: total, + amount_str: field_utils.format.monetary(Math.abs(total), {}, formatOptions), + currency_id: isOtherCurrencyId, + amount_currency: isOtherCurrencyId ? amount_currency : total, + amount_currency_str: isOtherCurrencyId ? field_utils.format.monetary(Math.abs(amount_currency), {}, { + currency_id: isOtherCurrencyId + }) : false, + account_code: self.accounts[line.st_line.open_balance_account_id], + }; + line.balance.show_balance = line.balance.amount_currency != 0; + line.balance.type = line.balance.amount_currency ? (line.st_line.partner_id ? 0 : -1) : 1; + }); + }, + /** + * + * + * @private + * @param {string} handle + * @param {integer} reconcileModelId + */ + _computeReconcileModels: function (handle, reconcileModelId) { + var line = this.getLine(handle); + // if quick create with 2 lines who use 100%, change the both values in same time + var props = _.filter(line.reconciliation_proposition, {'reconcileModelId': reconcileModelId, '__focus': true}); + if (props.length === 2 && props[0].percent && props[1].percent) { + if (props[0].percent + props[1].percent === 100) { + props[0].base_amount = props[0].amount = line.st_line.amount - props[1].base_amount; + props[0].__tax_to_recompute = true; + } + } + }, + /** + * format a name_get into an object {id, display_name}, idempotent + * + * @private + * @param {Object|Array} [value] data or name_get + */ + _formatNameGet: function (value) { + return value ? (value.id ? value : {'id': value[0], 'display_name': value[1]}) : false; + }, + _formatMany2ManyTags: function (value) { + var res = []; + for (var i=0, len=value.length; i 0){ + var hasDifferentPartners = function(prop){ + return !prop.partner_id || prop.partner_id != line.reconciliation_proposition[0].partner_id; + }; + + if(!_.any(line.reconciliation_proposition, hasDifferentPartners)){ + return self.changePartner(line.handle, { + 'id': line.reconciliation_proposition[0].partner_id, + 'display_name': line.reconciliation_proposition[0].partner_name, + }, true); + } + }else if(!line.st_line.partner_id && line.partner_id && line.partner_name){ + return self.changePartner(line.handle, { + 'id': line.partner_id, + 'display_name': line.partner_name, + }, true); + } + return true; + }) + .then(function(){ + return data.write_off ? self.quickCreateProposition(line.handle, data.model_id) : true; + }) + .then(function() { + // If still no partner set, take the one from context, if it exists + if (!line.st_line.partner_id && self.context.partner_id && self.context.partner_name) { + return self.changePartner(line.handle, { + 'id': self.context.partner_id, + 'display_name': self.context.partner_name, + }, true); + } + return true; + }) + ); + }); + return Promise.all(defs); + }, + /** + * Format the server value then compute the line + * overridden in ManualModel + * + * @see '_computeLine' + * + * @private + * @param {string} handle + * @param {Object[]} mv_lines + * @returns {Promise} + */ + _formatMoveLine: function (handle, mode, mv_lines) { + var self = this; + var line = this.getLine(handle); + line['mv_lines_'+mode] = _.uniq(line['mv_lines_'+mode].concat(mv_lines), l => l.id); + if (mv_lines[0]){ + line['remaining_'+mode] = mv_lines[0].recs_count - mv_lines.length; + } else if (line['mv_lines_'+mode].lenght == 0) { + line['remaining_'+mode] = 0; + } + this._formatLineProposition(line, mv_lines); + + if ((line.mode == 'match_other' || line.mode == "match_rp") && !line['mv_lines_'+mode].length && !line['filter_'+mode].length) { + line.mode = self._getDefaultMode(handle); + if (line.mode !== 'match_rp' && line.mode !== 'match_other' && line.mode !== 'inactive') { + return this._computeLine(line).then(function () { + return self.createProposition(handle); + }); + } + } else { + return this._computeLine(line); + } + }, + /** + * overridden in ManualModel + */ + _getDefaultMode: function(handle) { + var line = this.getLine(handle); + if (line.balance.amount === 0 + && (!line.st_line.mv_lines_match_rp || line.st_line.mv_lines_match_rp.length === 0) + && (!line.st_line.mv_lines_match_other || line.st_line.mv_lines_match_other.length === 0)) { + return 'inactive'; + } + if (line.mv_lines_match_rp && line.mv_lines_match_rp.length) { + return 'match_rp'; + } + if (line.mv_lines_match_other && line.mv_lines_match_other.length) { + return 'match_other'; + } + return 'create'; + }, + _getAvailableModes: function(handle) { + var line = this.getLine(handle); + var modes = [] + if (line.mv_lines_match_rp && line.mv_lines_match_rp.length) { + modes.push('match_rp') + } + if (line.mv_lines_match_other && line.mv_lines_match_other.length) { + modes.push('match_other') + } + modes.push('create') + return modes + }, + /** + * Apply default values for the proposition, format datas and format the + * base_amount with the decimal number from the currency + * extended in ManualModel + * + * @private + * @param {Object} line + * @param {Object} values + * @returns {Object} + */ + _formatQuickCreate: function (line, values) { + values = values || {}; + var today = new moment().utc().format(); + var account = this._formatNameGet(values.account_id); + var formatOptions = { + currency_id: line.st_line.currency_id, + }; + var amount; + switch(values.amount_type) { + case 'percentage': + amount = line.balance.amount * values.amount / 100; + break; + case 'regex': + var matching = line.st_line.name.match(new RegExp(values.amount_from_label_regex)) + amount = 0; + if (matching && matching.length == 2) { + matching = matching[1].replace(new RegExp('\\D' + values.decimal_separator, 'g'), ''); + matching = matching.replace(values.decimal_separator, '.'); + amount = parseFloat(matching) || 0; + amount = line.balance.amount > 0 ? amount : -amount; + } + break; + case 'fixed': + amount = values.amount; + break; + default: + amount = values.amount !== undefined ? values.amount : line.balance.amount; + } + + + var prop = { + 'id': _.uniqueId('createLine'), + 'label': values.label || line.st_line.name, + 'account_id': account, + 'account_code': account ? this.accounts[account.id] : '', + 'analytic_account_id': this._formatNameGet(values.analytic_account_id), + 'analytic_tag_ids': this._formatMany2ManyTags(values.analytic_tag_ids || []), + 'journal_id': this._formatNameGet(values.journal_id), + 'tax_ids': this._formatMany2ManyTagsTax(values.tax_ids || []), + 'tag_ids': values.tag_ids, + 'tax_repartition_line_id': values.tax_repartition_line_id, + 'debit': 0, + 'credit': 0, + 'date': values.date ? values.date : field_utils.parse.date(today, {}, {isUTC: true}), + 'force_tax_included': values.force_tax_included || false, + 'base_amount': amount, + 'percent': values.amount_type === "percentage" ? values.amount : null, + 'link': values.link, + 'display': true, + 'invalid': true, + 'to_check': !!values.to_check, + '__tax_to_recompute': true, + '__focus': '__focus' in values ? values.__focus : true, + }; + if (prop.base_amount) { + // Call to format and parse needed to round the value to the currency precision + var sign = prop.base_amount < 0 ? -1 : 1; + var amount = field_utils.format.monetary(Math.abs(prop.base_amount), {}, formatOptions); + prop.base_amount = sign * field_utils.parse.monetary(amount, {}, formatOptions); + } + + prop.amount = prop.base_amount; + return prop; + }, + /** + * Return list of account_move_line that has been selected and needs to be removed + * from other calls. + * + * @private + * @returns {Array} list of excluded ids + */ + _getExcludedIds: function () { + var excludedIds = []; + _.each(this.lines, function(line) { + if (line.reconciliation_proposition) { + _.each(line.reconciliation_proposition, function(prop) { + if (parseInt(prop['id'])) { + excludedIds.push(prop['id']); + } + }); + } + }); + return excludedIds; + }, + /** + * Defined whether the line is to be displayed or not. Here, we only display + * the line if it comes from the server or if an account is defined when it + * is created + * extended in ManualModel + * + * @private + * @param {object} prop + * @returns {Boolean} + */ + _isDisplayedProposition: function (prop) { + return !isNaN(prop.id) || !!prop.account_id; + }, + /** + * extended in ManualModel + * @private + * @param {object} prop + * @returns {Boolean} + */ + _isValid: function (prop) { + return !isNaN(prop.id) || prop.account_id && prop.amount && prop.label && !!prop.label.length; + }, + /** + * Fetch 'account.reconciliation.widget' propositions. + * overridden in ManualModel + * + * @see '_formatMoveLine' + * + * @private + * @param {string} handle + * @returns {Promise} + */ + _performMoveLine: function (handle, mode, limit) { + limit = limit || this.limitMoveLines; + var line = this.getLine(handle); + var excluded_ids = _.map(_.union(line.reconciliation_proposition, line.mv_lines_match_rp, line.mv_lines_match_other), function (prop) { + return _.isNumber(prop.id) ? prop.id : null; + }).filter(id => id != null); + var filter = line['filter_'+mode] || ""; + return this._rpc({ + model: 'account.reconciliation.widget', + method: 'get_move_lines_for_bank_statement_line', + args: [line.id, line.st_line.partner_id, excluded_ids, filter, 0, limit, mode === 'match_rp' ? 'rp' : 'other'], + context: this.context, + }) + .then(this._formatMoveLine.bind(this, handle, mode)); + }, + /** + * format the proposition to send information server side + * extended in ManualModel + * + * @private + * @param {object} line + * @param {object} prop + * @returns {object} + */ + _formatToProcessReconciliation: function (line, prop) { + var amount = -prop.amount; + if (prop.partial_amount) { + amount = -prop.partial_amount; + } + + var result = { + name : prop.label, + debit : amount > 0 ? amount : 0, + credit : amount < 0 ? -amount : 0, + tax_exigible: prop.tax_exigible, + analytic_tag_ids: [[6, null, _.pluck(prop.analytic_tag_ids, 'id')]] + }; + if (!isNaN(prop.id)) { + result.counterpart_aml_id = prop.id; + } else { + result.account_id = prop.account_id.id; + if (prop.journal_id) { + result.journal_id = prop.journal_id.id; + } + } + if (!isNaN(prop.id)) result.counterpart_aml_id = prop.id; + if (prop.analytic_account_id) result.analytic_account_id = prop.analytic_account_id.id; + if (prop.tax_ids && prop.tax_ids.length) result.tax_ids = [[6, null, _.pluck(prop.tax_ids, 'id')]]; + + if (prop.tag_ids && prop.tag_ids.length) result.tag_ids = [[6, null, prop.tag_ids]]; + if (prop.tax_repartition_line_id) result.tax_repartition_line_id = prop.tax_repartition_line_id; + if (prop.reconcileModelId) result.reconcile_model_id = prop.reconcileModelId + return result; + }, + /** + * Hook to handle return values of the validate's line process. + * + * @private + * @param {Object} data + * @param {Object[]} data.moves list of processed account.move + * @returns {Deferred} + */ + _validatePostProcess: function (data) { + var self = this; + return Promise.resolve(); + }, +}); + + +/** + * Model use to fetch, format and update 'account.move.line' and 'res.partner' + * datas allowing manual reconciliation + */ +var ManualModel = StatementModel.extend({ + quickCreateFields: ['account_id', 'journal_id', 'amount', 'analytic_account_id', 'label', 'tax_ids', 'force_tax_included', 'analytic_tag_ids', 'date', 'to_check'], + + modes: ['create', 'match'], + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * Return a boolean telling if load button needs to be displayed or not + * + * @returns {boolean} true if load more button needs to be displayed + */ + hasMoreLines: function () { + if (this.manualLines.length > this.pagerIndex) { + return true; + } + return false; + }, + /** + * load data from + * - 'account.reconciliation.widget' fetch the lines to reconciliate + * - 'account.account' fetch all account code + * + * @param {Object} context + * @param {string} [context.mode] 'customers', 'suppliers' or 'accounts' + * @param {integer[]} [context.company_ids] + * @param {integer[]} [context.partner_ids] used for 'customers' and + * 'suppliers' mode + * @returns {Promise} + */ + load: function (context) { + var self = this; + this.context = context; + + var domain_account_id = []; + if (context && context.company_ids) { + domain_account_id.push(['company_id', 'in', context.company_ids]); + } + + var def_account = this._rpc({ + model: 'account.account', + method: 'search_read', + domain: domain_account_id, + fields: ['code'], + }) + .then(function (accounts) { + self.account_ids = _.pluck(accounts, 'id'); + self.accounts = _.object(self.account_ids, _.pluck(accounts, 'code')); + }); + + var domainReconcile = []; + var session_allowed_company_ids = session.user_context.allowed_company_ids || [] + var company_ids = context && context.company_ids || session_allowed_company_ids.slice(0, 1); + + if (company_ids) { + domainReconcile.push(['company_id', 'in', company_ids]); + } + var def_reconcileModel = this._loadReconciliationModel({domainReconcile: domainReconcile}); + var def_taxes = this._loadTaxes(); + + return Promise.all([def_reconcileModel, def_account, def_taxes]).then(function () { + switch(context.mode) { + case 'customers': + case 'suppliers': + var mode = context.mode === 'customers' ? 'receivable' : 'payable'; + var args = ['partner', context.partner_ids || null, mode]; + return self._rpc({ + model: 'account.reconciliation.widget', + method: 'get_data_for_manual_reconciliation', + args: args, + context: context, + }) + .then(function (result) { + self.manualLines = result; + self.valuenow = 0; + self.valuemax = Object.keys(self.manualLines).length; + var lines = self.manualLines.slice(0, self.defaultDisplayQty); + self.pagerIndex = lines.length; + return self.loadData(lines); + }); + case 'accounts': + return self._rpc({ + model: 'account.reconciliation.widget', + method: 'get_data_for_manual_reconciliation', + args: ['account', context.account_ids || self.account_ids], + context: context, + }) + .then(function (result) { + self.manualLines = result; + self.valuenow = 0; + self.valuemax = Object.keys(self.manualLines).length; + var lines = self.manualLines.slice(0, self.defaultDisplayQty); + self.pagerIndex = lines.length; + return self.loadData(lines); + }); + default: + var partner_ids = context.partner_ids || null; + var account_ids = context.account_ids || self.account_ids || null; + return self._rpc({ + model: 'account.reconciliation.widget', + method: 'get_all_data_for_manual_reconciliation', + args: [partner_ids, account_ids], + context: context, + }) + .then(function (result) { + // Flatten the result + self.manualLines = [].concat(result.accounts, result.customers, result.suppliers); + self.valuenow = 0; + self.valuemax = Object.keys(self.manualLines).length; + var lines = self.manualLines.slice(0, self.defaultDisplayQty); + self.pagerIndex = lines.length; + return self.loadData(lines); + }); + } + }); + }, + + /** + * Reload data by calling load + * It overrides super.reload() because + * it is not adapted for this model. + * + * Use case: coming back to manual reconcilation + * in breadcrumb + */ + reload: function () { + this.lines = {}; + return this.load(this.context); + }, + + /** + * Load more partners/accounts + * overridden in ManualModel + * + * @param {integer} qty quantity to load + * @returns {Promise} + */ + loadMore: function(qty) { + if (qty === undefined) { + qty = this.defaultDisplayQty; + } + var lines = this.manualLines.slice(this.pagerIndex, this.pagerIndex + qty); + this.pagerIndex += qty; + return this.loadData(lines); + }, + /** + * Method to load informations on lines + * + * @param {Array} lines manualLines to load + * @returns {Promise} + */ + loadData: function(lines) { + var self = this; + var defs = []; + _.each(lines, function (l) { + defs.push(self._formatLine(l.mode, l)); + }); + return Promise.all(defs); + + }, + /** + * Mark the account or the partner as reconciled + * + * @param {(string|string[])} handle + * @returns {Promise} resolved with the handle array + */ + validate: function (handle) { + var self = this; + var handles = []; + if (handle) { + handles = [handle]; + } else { + _.each(this.lines, function (line, handle) { + if (!line.reconciled && !line.balance.amount && line.reconciliation_proposition.length) { + handles.push(handle); + } + }); + } + + var def = Promise.resolve(); + var process_reconciliations = []; + var reconciled = []; + _.each(handles, function (handle) { + var line = self.getLine(handle); + if(line.reconciled) { + return; + } + var props = line.reconciliation_proposition; + if (!props.length) { + self.valuenow++; + reconciled.push(handle); + line.reconciled = true; + process_reconciliations.push({ + id: line.type === 'accounts' ? line.account_id : line.partner_id, + type: line.type, + mv_line_ids: [], + new_mv_line_dicts: [], + }); + } else { + var mv_line_ids = _.pluck(_.filter(props, function (prop) {return !isNaN(prop.id);}), 'id'); + var new_mv_line_dicts = _.map(_.filter(props, function (prop) {return isNaN(prop.id) && prop.display;}), self._formatToProcessReconciliation.bind(self, line)); + process_reconciliations.push({ + id: null, + type: null, + mv_line_ids: mv_line_ids, + new_mv_line_dicts: new_mv_line_dicts + }); + } + line.reconciliation_proposition = []; + }); + if (process_reconciliations.length) { + def = self._rpc({ + model: 'account.reconciliation.widget', + method: 'process_move_lines', + args: [process_reconciliations], + }); + } + + return def.then(function() { + var defs = []; + var account_ids = []; + var partner_ids = []; + _.each(handles, function (handle) { + var line = self.getLine(handle); + if (line.reconciled) { + return; + } + line.filter_match = ""; + defs.push(self._performMoveLine(handle, 'match').then(function () { + if(!line.mv_lines_match.length) { + self.valuenow++; + reconciled.push(handle); + line.reconciled = true; + if (line.type === 'accounts') { + account_ids.push(line.account_id.id); + } else { + partner_ids.push(line.partner_id); + } + } + })); + }); + return Promise.all(defs).then(function () { + if (partner_ids.length) { + self._rpc({ + model: 'res.partner', + method: 'mark_as_reconciled', + args: [partner_ids], + }); + } + return {reconciled: reconciled, updated: _.difference(handles, reconciled)}; + }); + }); + }, + removeProposition: function (handle, id) { + var self = this; + var line = this.getLine(handle); + var defs = []; + var prop = _.find(line.reconciliation_proposition, {'id' : id}); + if (prop) { + line.reconciliation_proposition = _.filter(line.reconciliation_proposition, function (p) { + return p.id !== prop.id && p.id !== prop.link && p.link !== prop.id && (!p.link || p.link !== prop.link); + }); + line.mv_lines_match = line.mv_lines_match || []; + line.mv_lines_match.unshift(prop); + + // No proposition left and then, reset the st_line partner. + if(line.reconciliation_proposition.length == 0 && line.st_line.has_no_partner) + defs.push(self.changePartner(line.handle)); + } + line.mode = (id || line.mode !== "create") && isNaN(id) ? 'create' : 'match'; + defs.push(this._computeLine(line)); + return Promise.all(defs).then(function() { + return self.changeMode(handle, line.mode, true); + }) + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * override change the balance type to display or not the reconcile button + * + * @override + * @private + * @param {Object} line + * @returns {Promise} + */ + _computeLine: function (line) { + return this._super(line).then(function () { + var props = _.reject(line.reconciliation_proposition, 'invalid'); + _.each(line.reconciliation_proposition, function(p) { + delete p.is_move_line; + }); + line.balance.type = -1; + if (!line.balance.amount_currency && props.length) { + line.balance.type = 1; + } else if(_.any(props, function (prop) {return prop.amount > 0;}) && + _.any(props, function (prop) {return prop.amount < 0;})) { + line.balance.type = 0; + } + }); + }, + /** + * Format each server lines and propositions and compute all lines + * + * @see '_computeLine' + * + * @private + * @param {'customers' | 'suppliers' | 'accounts'} type + * @param {Object} data + * @returns {Promise} + */ + _formatLine: function (type, data) { + var line = this.lines[_.uniqueId('rline')] = _.extend(data, { + type: type, + reconciled: false, + mode: 'inactive', + limitMoveLines: this.limitMoveLines, + filter_match: "", + reconcileModels: this.reconcileModels, + account_id: this._formatNameGet([data.account_id, data.account_name]), + st_line: data, + visible: true + }); + this._formatLineProposition(line, line.reconciliation_proposition); + if (!line.reconciliation_proposition.length) { + delete line.reconciliation_proposition; + } + return this._computeLine(line); + }, + /** + * override to add journal_id + * + * @override + * @private + * @param {Object} line + * @param {Object} props + */ + _formatLineProposition: function (line, props) { + var self = this; + this._super(line, props); + if (props.length) { + _.each(props, function (prop) { + var tmp_value = prop.debit || prop.credit; + prop.credit = prop.credit !== 0 ? 0 : tmp_value; + prop.debit = prop.debit !== 0 ? 0 : tmp_value; + prop.amount = -prop.amount; + prop.journal_id = self._formatNameGet(prop.journal_id || line.journal_id); + prop.to_check = !!prop.to_check; + }); + } + }, + /** + * override to add journal_id on tax_created_line + * + * @private + * @param {Object} line + * @param {Object} values + * @returns {Object} + */ + _formatQuickCreate: function (line, values) { + // Add journal to created line + if (values && values.journal_id === undefined && line && line.createForm && line.createForm.journal_id) { + values.journal_id = line.createForm.journal_id; + } + return this._super(line, values); + }, + /** + * @override + * @param {object} prop + * @returns {Boolean} + */ + _isDisplayedProposition: function (prop) { + return !!prop.journal_id && this._super(prop); + }, + /** + * @override + * @param {object} prop + * @returns {Boolean} + */ + _isValid: function (prop) { + return prop.journal_id && this._super(prop); + }, + /** + * Fetch 'account.move.line' propositions. + * + * @see '_formatMoveLine' + * + * @override + * @private + * @param {string} handle + * @returns {Promise} + */ + _performMoveLine: function (handle, mode, limit) { + limit = limit || this.limitMoveLines; + var line = this.getLine(handle); + var excluded_ids = _.map(_.union(line.reconciliation_proposition, line.mv_lines_match), function (prop) { + return _.isNumber(prop.id) ? prop.id : null; + }).filter(id => id != null); + var filter = line.filter_match || ""; + var args = [line.account_id.id, line.partner_id, excluded_ids, filter, 0, limit]; + return this._rpc({ + model: 'account.reconciliation.widget', + method: 'get_move_lines_for_manual_reconciliation', + args: args, + context: this.context, + }) + .then(this._formatMoveLine.bind(this, handle, '')); + }, + + _formatToProcessReconciliation: function (line, prop) { + var result = this._super(line, prop); + result['date'] = prop.date; + return result; + }, + _getDefaultMode: function(handle) { + var line = this.getLine(handle); + if (line.balance.amount === 0 && (!line.st_line.mv_lines_match || line.st_line.mv_lines_match.length === 0)) { + return 'inactive'; + } + return line.mv_lines_match.length > 0 ? 'match' : 'create'; + }, + _formatMoveLine: function (handle, mode, mv_lines) { + var self = this; + var line = this.getLine(handle); + line.mv_lines_match = _.uniq((line.mv_lines_match || []).concat(mv_lines), l => l.id); + this._formatLineProposition(line, mv_lines); + + if (line.mode !== 'create' && !line.mv_lines_match.length && !line.filter_match.length) { + line.mode = this.avoidCreate || !line.balance.amount ? 'inactive' : 'create'; + if (line.mode === 'create') { + return this._computeLine(line).then(function () { + return self.createProposition(handle); + }); + } + } else { + return this._computeLine(line); + } + }, +}); + +return { + StatementModel: StatementModel, + ManualModel: ManualModel, +}; +}); diff --git a/base_accounting_kit/static/src/js/payment_render.js b/base_accounting_kit/static/src/js/payment_render.js new file mode 100644 index 000000000..96266ce9b --- /dev/null +++ b/base_accounting_kit/static/src/js/payment_render.js @@ -0,0 +1,929 @@ +odoo.define('base_accounting_kit.ReconciliationRenderer', function (require) { +"use strict"; + +var Widget = require('web.Widget'); +var FieldManagerMixin = require('web.FieldManagerMixin'); +var relational_fields = require('web.relational_fields'); +var basic_fields = require('web.basic_fields'); +var core = require('web.core'); +var time = require('web.time'); +var session = require('web.session'); +var qweb = core.qweb; +var _t = core._t; + + +/** + * rendering of the bank statement action contains progress bar, title and + * auto reconciliation button + */ +var StatementRenderer = Widget.extend(FieldManagerMixin, { + template: 'reconciliation.statement', + events: { + 'click *[rel="do_action"]': '_onDoAction', + 'click button.js_load_more': '_onLoadMore', + }, + /** + * @override + */ + init: function (parent, model, state) { + this._super(parent); + this.model = model; + this._initialState = state; + }, + /** + * display iniial state and create the name statement field + * + * @override + */ + start: function () { + var self = this; + var defs = [this._super.apply(this, arguments)]; + this.time = Date.now(); + this.$progress = $(''); + + return Promise.all(defs); + }, + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + /* + * hide the button to load more statement line + */ + hideLoadMoreButton: function (show) { + if (!show) { + this.$('.js_load_more').show(); + } + else { + this.$('.js_load_more').hide(); + } + }, + showRainbowMan: function (state) { + if (this.model.display_context !== 'validate') { + return + } + var dt = Date.now()-this.time; + var $done = $(qweb.render("reconciliation.done", { + 'duration': moment(dt).utc().format(time.getLangTimeFormat()), + 'number': state.valuenow, + 'timePerTransaction': Math.round(dt/1000/state.valuemax), + 'context': state.context, + })); + $done.find('*').addClass('o_reward_subcontent'); + $done.find('.button_close_statement').click(this._onCloseBankStatement.bind(this)); + $done.find('.button_back_to_statement').click(this._onGoToBankStatement.bind(this)); + // display rainbowman after full reconciliation + if (session.show_effect) { + this.trigger_up('show_effect', { + type: 'rainbow_man', + fadeout: 'no', + message: $done, + }); + this.$el.css('min-height', '450px'); + } else { + $done.appendTo(this.$el); + } + }, + /** + * update the statement rendering + * + * @param {object} state - statement data + * @param {integer} state.valuenow - for the progress bar + * @param {integer} state.valuemax - for the progress bar + * @param {string} state.title - for the progress bar + * @param {[object]} [state.notifications] + */ + update: function (state) { + var self = this; + this._updateProgressBar(state); + + if (state.valuenow === state.valuemax && !this.$('.done_message').length) { + this.showRainbowMan(state); + } + + if (state.notifications) { + this._renderNotifications(state.notifications); + } + }, + _updateProgressBar: function(state) { + this.$progress.find('.valuenow').text(state.valuenow); + this.$progress.find('.valuemax').text(state.valuemax); + this.$progress.find('.progress-bar') + .attr('aria-valuenow', state.valuenow) + .attr('aria-valuemax', state.valuemax) + .css('width', (state.valuenow/state.valuemax*100) + '%'); + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + /** + * render the notifications + * + * @param {[object]} notifications + */ + _renderNotifications: function(notifications) { + this.$(".notification_area").empty(); + for (var i=0; i') + .appendTo(this.$('thead .cell_info_popover')) + .attr("data-content", qweb.render('reconciliation.line.statement_line.details', {'state': this._initialState})); + this.$el.popover({ + 'selector': '.line_info_button', + 'placement': 'left', + 'container': this.$el, + 'html': true, + // disable bootstrap sanitizer because we use a table that has been + // rendered using qweb.render so it is safe and also because sanitizer escape table by default. + 'sanitize': false, + 'trigger': 'hover', + 'animation': false, + 'toggle': 'popover' + }); + var def2 = this._super.apply(this, arguments); + return Promise.all([def1, def2, def3, def4]); + }, + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * update the statement line rendering + * + * @param {object} state - statement line + */ + update: function (state) { + var self = this; + // isValid + var to_check_checked = !!(state.to_check); + this.$('caption .o_buttons button.o_validate').toggleClass('d-none', !!state.balance.type && !to_check_checked); + this.$('caption .o_buttons button.o_reconcile').toggleClass('d-none', state.balance.type <= 0 || to_check_checked); + this.$('caption .o_buttons .o_no_valid').toggleClass('d-none', state.balance.type >= 0 || to_check_checked); + self.$('caption .o_buttons button.o_validate').toggleClass('text-warning', to_check_checked); + + // partner_id + this._makePartnerRecord(state.st_line.partner_id, state.st_line.partner_name).then(function (recordID) { + self.fields.partner_id.reset(self.model.get(recordID)); + self.$el.attr('data-partner', state.st_line.partner_id); + }); + + // mode + this.$el.data('mode', state.mode).attr('data-mode', state.mode); + this.$('.o_notebook li a').attr('aria-selected', false); + this.$('.o_notebook li a').removeClass('active'); + this.$('.o_notebook .tab-content .tab-pane').removeClass('active'); + this.$('.o_notebook li a[href*="notebook_page_' + state.mode + '"]').attr('aria-selected', true); + this.$('.o_notebook li a[href*="notebook_page_' + state.mode + '"]').addClass('active'); + this.$('.o_notebook .tab-content .tab-pane[id*="notebook_page_' + state.mode + '"]').addClass('active'); + this.$('.create, .match').each(function () { + $(this).removeAttr('style'); + }); + + // reconciliation_proposition + var $props = this.$('.accounting_view tbody').empty(); + + // Search propositions that could be a partial credit/debit. + var props = []; + var balance = state.balance.amount_currency; + _.each(state.reconciliation_proposition, function (prop) { + if (prop.display) { + props.push(prop); + } + }); + + _.each(props, function (line) { + var $line = $(qweb.render("reconciliation.line.mv_line", {'line': line, 'state': state, 'proposition': true})); + if (!isNaN(line.id)) { + $('') + .appendTo($line.find('.cell_info_popover')) + .attr("data-content", qweb.render('reconciliation.line.mv_line.details', {'line': line})); + } + $props.append($line); + }); + + // mv_lines + var matching_modes = self.model.modes.filter(x => x.startsWith('match')); + for (let i = 0; i < matching_modes.length; i++) { + var stateMvLines = state['mv_lines_'+matching_modes[i]] || []; + var recs_count = stateMvLines.length > 0 ? stateMvLines[0].recs_count : 0; + var remaining = state['remaining_' + matching_modes[i]]; + var $mv_lines = this.$('div[id*="notebook_page_' + matching_modes[i] + '"] .match table tbody').empty(); + this.$('.o_notebook li a[href*="notebook_page_' + matching_modes[i] + '"]').parent().toggleClass('d-none', stateMvLines.length === 0 && !state['filter_'+matching_modes[i]]); + + _.each(stateMvLines, function (line) { + var $line = $(qweb.render("reconciliation.line.mv_line", {'line': line, 'state': state})); + if (!isNaN(line.id)) { + $('') + .appendTo($line.find('.cell_info_popover')) + .attr("data-content", qweb.render('reconciliation.line.mv_line.details', {'line': line})); + } + $mv_lines.append($line); + }); + this.$('div[id*="notebook_page_' + matching_modes[i] + '"] .match div.load-more').toggle(remaining > 0); + this.$('div[id*="notebook_page_' + matching_modes[i] + '"] .match div.load-more span').text(remaining); + } + + // balance + this.$('.popover').remove(); + this.$('table tfoot').html(qweb.render("reconciliation.line.balance", {'state': state})); + + // create form + if (state.createForm) { + var createPromise; + if (!this.fields.account_id) { + createPromise = this._renderCreate(state); + } + Promise.resolve(createPromise).then(function(){ + var data = self.model.get(self.handleCreateRecord).data; + return self.model.notifyChanges(self.handleCreateRecord, state.createForm) + .then(function () { + // FIXME can't it directly written REPLACE_WITH ids=state.createForm.analytic_tag_ids + return self.model.notifyChanges(self.handleCreateRecord, {analytic_tag_ids: {operation: 'REPLACE_WITH', ids: []}}) + }) + .then(function (){ + var defs = []; + _.each(state.createForm.analytic_tag_ids, function (tag) { + defs.push(self.model.notifyChanges(self.handleCreateRecord, {analytic_tag_ids: {operation: 'ADD_M2M', ids: tag}})); + }); + return Promise.all(defs); + }) + .then(function () { + return self.model.notifyChanges(self.handleCreateRecord, {tax_ids: {operation: 'REPLACE_WITH', ids: []}}) + }) + .then(function (){ + var defs = []; + _.each(state.createForm.tax_ids, function (tag) { + defs.push(self.model.notifyChanges(self.handleCreateRecord, {tax_ids: {operation: 'ADD_M2M', ids: tag}})); + }); + return Promise.all(defs); + }) + .then(function () { + var record = self.model.get(self.handleCreateRecord); + _.each(self.fields, function (field, fieldName) { + if (self._avoidFieldUpdate[fieldName]) return; + if (fieldName === "partner_id") return; + if ((data[fieldName] || state.createForm[fieldName]) && !_.isEqual(state.createForm[fieldName], data[fieldName])) { + field.reset(record); + } + if (fieldName === 'tax_ids') { + if (!state.createForm[fieldName].length || state.createForm[fieldName].length > 1) { + $('.create_force_tax_included').addClass('d-none'); + } + else { + $('.create_force_tax_included').removeClass('d-none'); + var price_include = state.createForm[fieldName][0].price_include; + var force_tax_included = state.createForm[fieldName][0].force_tax_included; + self.$('.create_force_tax_included input').prop('checked', force_tax_included); + self.$('.create_force_tax_included input').prop('disabled', price_include); + } + } + }); + if (state.to_check) { + // Set the to_check field to true if global to_check is set + self.$('.create_to_check input').prop('checked', state.to_check).change(); + } + return true; + }); + }); + } + this.$('.create .add_line').toggle(!!state.balance.amount_currency); + }, + + updatePartialAmount: function(line_id, amount) { + var $line = this.$('.mv_line[data-line-id='+line_id+']'); + $line.find('.edit_amount').addClass('d-none'); + $line.find('.edit_amount_input').removeClass('d-none'); + $line.find('.edit_amount_input').focus(); + $line.find('.edit_amount_input').val(amount); + $line.find('.line_amount').addClass('d-none'); + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @private + * @param {jQueryElement} $el + */ + _destroyPopover: function ($el) { + var popover = $el.data('bs.popover'); + if (popover) { + popover.dispose(); + } + }, + /** + * @private + * @param {integer} partnerID + * @param {string} partnerName + * @returns {string} local id of the dataPoint + */ + _makePartnerRecord: function (partnerID, partnerName) { + var field = { + relation: 'res.partner', + type: 'many2one', + name: 'partner_id', + }; + if (partnerID) { + field.value = [partnerID, partnerName]; + } + return this.model.makeRecord('account.bank.statement.line', [field], { + partner_id: { + domain: ["|", ["is_company", "=", true], ["parent_id", "=", false]], + options: { + no_open: true + } + } + }); + }, + + /** + * create account_id, tax_ids, analytic_account_id, analytic_tag_ids, label and amount fields + * + * @private + * @param {object} state - statement line + * @returns {Promise} + */ + _renderCreate: function (state) { + var self = this; + return this.model.makeRecord('account.bank.statement.line', [{ + relation: 'account.account', + type: 'many2one', + name: 'account_id', + domain: [['company_id', '=', state.st_line.company_id], ['deprecated', '=', false]], + }, { + relation: 'account.journal', + type: 'many2one', + name: 'journal_id', + domain: [['company_id', '=', state.st_line.company_id]], + }, { + relation: 'account.tax', + type: 'many2many', + name: 'tax_ids', + domain: [['company_id', '=', state.st_line.company_id]], + }, { + relation: 'account.analytic.account', + type: 'many2one', + name: 'analytic_account_id', + }, { + relation: 'account.analytic.tag', + type: 'many2many', + name: 'analytic_tag_ids', + }, { + type: 'boolean', + name: 'force_tax_included', + }, { + type: 'char', + name: 'label', + }, { + type: 'float', + name: 'amount', + }, { + type: 'char', //TODO is it a bug or a feature when type date exists ? + name: 'date', + }, { + type: 'boolean', + name: 'to_check', + }], { + account_id: { + string: _t("Account"), + }, + label: {string: _t("Label")}, + amount: {string: _t("Account")}, + }).then(function (recordID) { + self.handleCreateRecord = recordID; + var record = self.model.get(self.handleCreateRecord); + + self.fields.account_id = new relational_fields.FieldMany2One(self, + 'account_id', record, {mode: 'edit', attrs: {can_create:false}}); + + self.fields.journal_id = new relational_fields.FieldMany2One(self, + 'journal_id', record, {mode: 'edit'}); + + self.fields.tax_ids = new relational_fields.FieldMany2ManyTags(self, + 'tax_ids', record, {mode: 'edit', additionalContext: {append_type_to_tax_name: true}}); + + self.fields.analytic_account_id = new relational_fields.FieldMany2One(self, + 'analytic_account_id', record, {mode: 'edit'}); + + self.fields.analytic_tag_ids = new relational_fields.FieldMany2ManyTags(self, + 'analytic_tag_ids', record, {mode: 'edit'}); + + self.fields.force_tax_included = new basic_fields.FieldBoolean(self, + 'force_tax_included', record, {mode: 'edit'}); + + self.fields.label = new basic_fields.FieldChar(self, + 'label', record, {mode: 'edit'}); + + self.fields.amount = new basic_fields.FieldFloat(self, + 'amount', record, {mode: 'edit'}); + + self.fields.date = new basic_fields.FieldDate(self, + 'date', record, {mode: 'edit'}); + + self.fields.to_check = new basic_fields.FieldBoolean(self, + 'to_check', record, {mode: 'edit'}); + + var $create = $(qweb.render("reconciliation.line.create", {'state': state, 'group_tags': self.group_tags, 'group_acc': self.group_acc})); + self.fields.account_id.appendTo($create.find('.create_account_id .o_td_field')) + .then(addRequiredStyle.bind(self, self.fields.account_id)); + self.fields.journal_id.appendTo($create.find('.create_journal_id .o_td_field')); + self.fields.tax_ids.appendTo($create.find('.create_tax_id .o_td_field')); + self.fields.analytic_account_id.appendTo($create.find('.create_analytic_account_id .o_td_field')); + self.fields.analytic_tag_ids.appendTo($create.find('.create_analytic_tag_ids .o_td_field')); + self.fields.force_tax_included.appendTo($create.find('.create_force_tax_included .o_td_field')); + self.fields.label.appendTo($create.find('.create_label .o_td_field')) + .then(addRequiredStyle.bind(self, self.fields.label)); + self.fields.amount.appendTo($create.find('.create_amount .o_td_field')) + .then(addRequiredStyle.bind(self, self.fields.amount)); + self.fields.date.appendTo($create.find('.create_date .o_td_field')); + self.fields.to_check.appendTo($create.find('.create_to_check .o_td_field')); + self.$('.create').append($create); + + function addRequiredStyle(widget) { + widget.$el.addClass('o_required_modifier'); + } + }); + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + /** + * The event on the partner m2o widget was propagated to the bank statement + * line widget, causing it to expand and the others to collapse. This caused + * the dropdown to be poorly placed and an unwanted update of this widget. + * + * @private + */ + _onStopPropagation: function(ev) { + ev.stopPropagation(); + }, + + /** + * @private + * @param {MouseEvent} event + */ + _onCreateReconcileModel: function (event) { + event.preventDefault(); + var self = this; + this.do_action({ + type: 'ir.actions.act_window', + res_model: 'account.reconcile.model', + views: [[false, 'form']], + target: 'current' + }, + { + on_reverse_breadcrumb: function() {self.trigger_up('reload');}, + }); + }, + _editAmount: function (event) { + event.stopPropagation(); + var $line = $(event.target); + var moveLineId = $line.closest('.mv_line').data('line-id'); + this.trigger_up('partial_reconcile', {'data': {mvLineId: moveLineId, 'amount': $line.val()}}); + }, + _onEditAmount: function (event) { + event.preventDefault(); + event.stopPropagation(); + // Don't call when clicking inside the input field + if (! $(event.target).hasClass('edit_amount_input')){ + var $line = $(event.target); + this.trigger_up('getPartialAmount', {'data': $line.closest('.mv_line').data('line-id')}); + } + }, + /** + * @private + * @param {MouseEvent} event + */ + _onEditReconcileModel: function (event) { + event.preventDefault(); + var self = this; + this.do_action({ + type: 'ir.actions.act_window', + res_model: 'account.reconcile.model', + views: [[false, 'list'], [false, 'form']], + view_mode: "list", + target: 'current' + }, + { + on_reverse_breadcrumb: function() {self.trigger_up('reload');}, + }); + }, + /** + * @private + * @param {OdooEvent} event + */ + _onFieldChanged: function (event) { + event.stopPropagation(); + var fieldName = event.target.name; + if (fieldName === 'partner_id') { + var partner_id = event.data.changes.partner_id; + this.trigger_up('change_partner', {'data': partner_id}); + } else { + if (event.data.changes.amount && isNaN(event.data.changes.amount)) { + return; + } + this.trigger_up('update_proposition', {'data': event.data.changes}); + } + }, + /** + * @private + */ + _onTogglePanel: function () { + if (this.$el[0].getAttribute('data-mode') == 'inactive') + this.trigger_up('change_mode', {'data': 'default'}); + }, + /** + * @private + */ + _onChangeTab: function(event) { + if (event.currentTarget.nodeName === 'TFOOT') { + this.trigger_up('change_mode', {'data': 'next'}); + } else { + var modes = this.model.modes; + var selected_mode = modes.find(function(e) {return event.target.getAttribute('href').includes(e)}); + if (selected_mode) { + this.trigger_up('change_mode', {'data': selected_mode}); + } + } + }, + /** + * @private + * @param {input event} event + */ + _onFilterChange: function (event) { + this.trigger_up('change_filter', {'data': _.str.strip($(event.target).val())}); + }, + /** + * @private + * @param {keyup event} event + */ + _onInputKeyup: function (event) { + var target_partner_id = $(event.target).parents('[name="partner_id"]'); + if (target_partner_id.length === 1) { + return; + } + if(event.keyCode === 13) { + if ($(event.target).hasClass('edit_amount_input')) { + $(event.target).blur(); + return; + } + var created_lines = _.findWhere(this.model.lines, {mode: 'create'}); + if (created_lines && created_lines.balance.amount) { + this._onCreateProposition(); + } + return; + } + if ($(event.target).hasClass('edit_amount_input')) { + if (event.type === 'keyup') { + return; + } + else { + return this._editAmount(event); + } + } + + var self = this; + for (var fieldName in this.fields) { + var field = this.fields[fieldName]; + if (!field.$el.is(event.target)) { + continue; + } + this._avoidFieldUpdate[field.name] = event.type !== 'focusout'; + field.value = false; + field._setValue($(event.target).val()).then(function () { + self._avoidFieldUpdate[field.name] = false; + }); + break; + } + }, + /** + * @private + */ + _onLoadMore: function (ev) { + ev.preventDefault(); + this.trigger_up('change_offset'); + }, + /** + * @private + * @param {MouseEvent} event + */ + _onSelectMoveLine: function (event) { + var $el = $(event.target); + $el.prop('disabled', true); + this._destroyPopover($el); + var moveLineId = $el.closest('.mv_line').data('line-id'); + this.trigger_up('add_proposition', {'data': moveLineId}); + }, + /** + * @private + * @param {MouseEvent} event + */ + _onSelectProposition: function (event) { + var $el = $(event.target); + this._destroyPopover($el); + var moveLineId = $el.closest('.mv_line').data('line-id'); + this.trigger_up('remove_proposition', {'data': moveLineId}); + }, + /** + * @private + * @param {MouseEvent} event + */ + _onQuickCreateProposition: function (event) { + document.activeElement && document.activeElement.blur(); + this.trigger_up('quick_create_proposition', {'data': $(event.target).data('reconcile-model-id')}); + }, + /** + * @private + */ + _onCreateProposition: function () { + document.activeElement && document.activeElement.blur(); + var invalid = []; + _.each(this.fields, function (field) { + if (!field.isValid()) { + invalid.push(field.string); + } + }); + if (invalid.length) { + this.do_warn(_t("Some fields are undefined"), invalid.join(', ')); + return; + } + this.trigger_up('create_proposition'); + }, + /** + * @private + */ + _onValidate: function () { + this.trigger_up('validate'); + } +}); + + +/** + * rendering of the manual reconciliation action contains progress bar, title + * and auto reconciliation button + */ +var ManualRenderer = StatementRenderer.extend({ + template: "reconciliation.manual.statement", + +}); + + +/** + * rendering of the manual reconciliation, contains line data, proposition and + * view for 'match' mode + */ +var ManualLineRenderer = LineRenderer.extend({ + template: "reconciliation.manual.line", + /** + * @override + * @param {string} handle + * @param {number} proposition id (move line id) + * @returns {Promise} + */ + removeProposition: function (handle, id) { + if (!id) { + return Promise.resolve(); + } + return this._super(handle, id); + }, + /** + * move the partner field + * + * @override + */ + start: function () { + var self = this; + return this._super.apply(this, arguments).then(function () { + return self.model.makeRecord('account.move.line', [{ + relation: 'account.account', + type: 'many2one', + name: 'account_id', + value: [self._initialState.account_id.id, self._initialState.account_id.display_name], + }]).then(function (recordID) { + self.fields.title_account_id = new relational_fields.FieldMany2One(self, + 'account_id', + self.model.get(recordID), + {mode: 'readonly'} + ); + }).then(function () { + return self.fields.title_account_id.appendTo(self.$('.accounting_view thead td:eq(0) span:first')); + }); + }); + }, + /** + * @override + */ + update: function (state) { + this._super(state); + var props = _.filter(state.reconciliation_proposition, {'display': true}); + if (!props.length) { + var $line = $(qweb.render("reconciliation.line.mv_line", {'line': {}, 'state': state})); + this.$('.accounting_view tbody').append($line); + } + }, + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + /** + * display journal_id field + * + * @override + */ + _renderCreate: function (state) { + var self = this; + var parentPromise = this._super(state).then(function() { + self.$('.create .create_journal_id').show(); + self.$('.create .create_date').removeClass('d-none'); + self.$('.create .create_journal_id .o_input').addClass('o_required_modifier'); + }); + return parentPromise; + }, + +}); + + +return { + StatementRenderer: StatementRenderer, + ManualRenderer: ManualRenderer, + LineRenderer: LineRenderer, + ManualLineRenderer: ManualLineRenderer, +}; +}); diff --git a/base_accounting_kit/static/src/xml/payment_matching.xml b/base_accounting_kit/static/src/xml/payment_matching.xml new file mode 100644 index 000000000..e96b3b941 --- /dev/null +++ b/base_accounting_kit/static/src/xml/payment_matching.xml @@ -0,0 +1,402 @@ + + + + +
+
+
+
+
+
+
+ + +
+
/
+
+
+ + +
+
+
+
+ +
+
+
+

Nothing to do!

+

This page displays all the bank transactions that are to be reconciled and provides with a neat interface to do so.

+
+ + + + + + + + + +

Good Job! There is nothing to reconcile.

+

All invoices and payments have been matched, your accounts' balances are clean.

+

+ From now on, you may want to: +

+

+
+
+ +
+

Congrats, you're all done!

+

You reconciled transactions in . + +
That's on average seconds per transaction. + +

+ +

+ + + + + + +

+
+
+ + + +
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+
()
+
+ +
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+
+
+ + + +
+ + + +
+
+ + + + + + + + + Last Reconciliation: + + + + + + + + + + + + + Open balanceChoose counterpart or Create Write-off + + + + + + + +
+
+ + +
+ + + +
+ +
+ + +
+
+
+ + + +

To speed up reconciliation, define reconciliation models.

+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ + + + + + + + +
+
+
+ + + + + + + + +
+
+ + + + + + + + New + + + + + + + : + + + + : + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Account
Date
Due Date
Journal
Partner
Label
Ref
Amount ()
Residual + () +
This payment is registered but not reconciled.
+
+ + + + + + + + + + + +
Date
Partner
Transaction
Description
Amount ()
Account
Note
+
+ + + + + + + statement lines + + have been reconciled automatically. + + + + + + + + + + + + + + +
+ + + + + + + +
+
+ + diff --git a/base_accounting_kit/views/assets.xml b/base_accounting_kit/views/assets.xml index 2d0aa3adc..5e2cdc776 100644 --- a/base_accounting_kit/views/assets.xml +++ b/base_accounting_kit/views/assets.xml @@ -5,6 +5,9 @@