1
0
forked from Mapan/odoo17e
odoo17e-kedaikipas58/addons/sale_account_accountant/models/account_reconcile_model.py
2024-12-10 09:04:09 +07:00

96 lines
3.8 KiB
Python

# -*- coding: utf-8 -*-
from dateutil.relativedelta import relativedelta
from odoo import models, fields
class AccountReconcileModel(models.Model):
_inherit = 'account.reconcile.model'
def _get_invoice_matching_so_candidates(self, st_line, partner):
""" Find a match between the bank transaction and some sale orders. If none of them are invoiced, there are
returned to display a message to the user allowing him to show the matched sale orders.
If some of them are already matched, the journal items are suggested to the user.
:param st_line: A statement line.
:param partner: The partner to consider.
:return:
{'allow_auto_reconcile': <bool>, 'amls': <account.move.line>} if some sale orders are invoiced.
{'sale_orders': <sale.order>} otherwise.
"""
assert self.rule_type == 'invoice_matching'
for model in ('sale.order', 'sale.order.line', 'account.move', 'account.move.line'):
self.env[model].flush_model()
_numerical_tokens, exact_tokens, text_tokens = self._get_invoice_matching_st_line_tokens(st_line)
if not (exact_tokens or text_tokens):
return
# Find the sale orders that are not yet invoiced or already invoices.
domain = [
('company_id', '=', st_line.company_id.id),
'|',
('invoice_status', 'in', ('to invoice', 'invoiced')),
('state', '=', 'sent'),
]
sale_orders = self.env['sale.order']
if exact_tokens:
sale_orders = self.env['sale.order'].search(domain + [('name', 'in', exact_tokens)])
if not sale_orders and text_tokens:
query = self.env['sale.order']._where_calc(domain)
tables, where_clause, where_params = query.get_sql()
self._cr.execute(
rf'''
WITH sale_order_name AS (
SELECT
sale_order.id,
SUBSTRING(REGEXP_REPLACE(LOWER(sale_order.name), '[^0-9a-z\s]', '', 'g'), '\S(?:.*\S)*') AS name
FROM {tables}
WHERE {where_clause}
)
SELECT sub.id
FROM sale_order_name sub
WHERE sub.name LIKE ANY(ARRAY[%s])
''',
where_params + [[t.lower() for t in set(text_tokens)]],
)
sale_order_ids = [r[0] for r in self._cr.fetchall()]
if sale_order_ids:
sale_orders = sale_orders.browse(sale_order_ids)
if sale_orders:
results = {'sale_orders': sale_orders}
# Find some related invoices.
aml_domain = self._get_invoice_matching_amls_domain(st_line, partner)
invoices = sale_orders.invoice_ids
if not invoices:
# The sale orders are not yet invoiced. Return them to allow the user to invoice them from
# the bank reco widget.
return results
invoice_amls = invoices.line_ids.filtered_domain(aml_domain)
matched_payments = invoices._get_reconciled_payments()
payments_amls = matched_payments.line_ids.filtered_domain(aml_domain)
amls = payments_amls | invoice_amls
if not amls:
# The invoices and their payments are all already reconciled. Don't match anything and let the others rules trying
# to match potential payments instead.
return
results['amls'] = amls
results['allow_auto_reconcile'] = True
return results
def _get_invoice_matching_rules_map(self):
# EXTENDS account
res = super()._get_invoice_matching_rules_map()
res[0].append(self._get_invoice_matching_so_candidates)
return res