import logging from datetime import datetime _logger = logging.getLogger(__name__) def get_unreconciled_bank_lines(env, params): domain = [('is_reconciled', '=', False), ('company_id', '=', env.company.id)] if params.get('journal_id'): domain.append(('journal_id', '=', int(params['journal_id']))) if params.get('date_from'): domain.append(('date', '>=', params['date_from'])) if params.get('date_to'): domain.append(('date', '<=', params['date_to'])) if params.get('min_amount'): domain.append(('amount', '>=', float(params['min_amount']))) limit = int(params.get('limit', 50)) lines = env['account.bank.statement.line'].search(domain, limit=limit, order='date desc') return { 'count': len(lines), 'total_amount': sum(abs(l.amount) for l in lines), 'lines': [{ 'id': l.id, 'date': str(l.date), 'payment_ref': l.payment_ref or '', 'partner_name': l.partner_name or (l.partner_id.name if l.partner_id else ''), 'amount': l.amount, 'journal': l.journal_id.name, } for l in lines], } def get_unreconciled_receipts(env, params): account_code = params.get('account_code', '1122') accounts = env['account.account'].search([ ('code', '=like', f'{account_code}%'), ('company_id', '=', env.company.id), ]) domain = [ ('account_id', 'in', accounts.ids), ('reconciled', '=', False), ('parent_state', '=', 'posted'), ('company_id', '=', env.company.id), ] lines = env['account.move.line'].search(domain, order='date desc') return { 'count': len(lines), 'total_amount': sum(abs(l.amount_residual) for l in lines), 'lines': [{ 'id': l.id, 'date': str(l.date), 'ref': l.ref or l.move_id.name, 'partner': l.partner_id.name if l.partner_id else '', 'amount_residual': l.amount_residual, } for l in lines], } def match_bank_line_to_payments(env, params): st_line_id = int(params['statement_line_id']) move_line_ids = [int(x) for x in params['move_line_ids']] st_line = env['account.bank.statement.line'].browse(st_line_id) if not st_line.exists(): return {'error': 'Statement line not found'} st_line.set_line_bank_statement_line(move_line_ids) return { 'status': 'matched', 'statement_line_id': st_line_id, 'matched_move_lines': move_line_ids, 'is_reconciled': st_line.is_reconciled, } def auto_reconcile_bank_lines(env, params): company_id = params.get('company_id', env.company.id) lines = env['account.bank.statement.line'].search([ ('is_reconciled', '=', False), ('company_id', '=', int(company_id)), ]) before_count = len(lines) lines._try_auto_reconcile_statement_lines(company_id=int(company_id)) still_unreconciled = env['account.bank.statement.line'].search([ ('is_reconciled', '=', False), ('company_id', '=', int(company_id)), ]) reconciled_count = before_count - len(still_unreconciled) return { 'status': 'completed', 'lines_before': before_count, 'lines_reconciled': reconciled_count, 'lines_remaining': len(still_unreconciled), } def apply_reconcile_model(env, params): model_id = int(params['model_id']) st_line_id = int(params['statement_line_id']) reco_model = env['account.reconcile.model'].browse(model_id) st_line = env['account.bank.statement.line'].browse(st_line_id) if not reco_model.exists() or not st_line.exists(): return {'error': 'Model or statement line not found'} _liquidity_lines, suspense_lines, _other_lines = st_line._seek_for_lines() residual = sum(l.amount_residual for l in suspense_lines) if suspense_lines else st_line.amount write_off_vals = reco_model._get_write_off_move_lines_dict(st_line, residual) if write_off_vals: line_ids_create_command = [(0, 0, vals) for vals in write_off_vals] st_line.move_id.write({'line_ids': line_ids_create_command}) return { 'status': 'applied', 'model': reco_model.name, 'write_off_lines': len(write_off_vals) if write_off_vals else 0, } def unmatch_bank_line(env, params): st_line_id = int(params['statement_line_id']) st_line = env['account.bank.statement.line'].browse(st_line_id) if not st_line.exists(): return {'error': 'Statement line not found'} st_line.action_unreconcile_entry() return {'status': 'unmatched', 'statement_line_id': st_line_id} def get_reconcile_suggestions(env, params): st_line_id = int(params['statement_line_id']) st_line = env['account.bank.statement.line'].browse(st_line_id) if not st_line.exists(): return {'error': 'Statement line not found'} models = env['account.reconcile.model'].search([ ('company_id', '=', env.company.id), ]) return { 'models': [{ 'id': m.id, 'name': m.name, 'trigger': m.trigger if hasattr(m, 'trigger') else 'manual', } for m in models], } def sum_payments_by_date(env, params): date_from = params.get('date_from') date_to = params.get('date_to') if not date_from or not date_to: return {'error': 'date_from and date_to are required'} journal_ids = params.get('journal_ids', []) domain = [ ('parent_state', '=', 'posted'), ('company_id', '=', env.company.id), ('date', '>=', date_from), ('date', '<=', date_to), ] if journal_ids: domain.append(('journal_id', 'in', [int(j) for j in journal_ids])) lines = env['account.move.line'].search(domain) total_debit = sum(l.debit for l in lines) total_credit = sum(l.credit for l in lines) return { 'date_from': date_from, 'date_to': date_to, 'total_debit': total_debit, 'total_credit': total_credit, 'net': total_debit - total_credit, 'line_count': len(lines), } TOOLS = { 'get_unreconciled_bank_lines': get_unreconciled_bank_lines, 'get_unreconciled_receipts': get_unreconciled_receipts, 'match_bank_line_to_payments': match_bank_line_to_payments, 'auto_reconcile_bank_lines': auto_reconcile_bank_lines, 'apply_reconcile_model': apply_reconcile_model, 'unmatch_bank_line': unmatch_bank_line, 'get_reconcile_suggestions': get_reconcile_suggestions, 'sum_payments_by_date': sum_payments_by_date, }