This commit is contained in:
gsinghpal
2026-05-16 13:18:52 -04:00
parent 191a9c82be
commit 9ebf89bde2
1080 changed files with 0 additions and 1197 deletions

Binary file not shown.

View File

@@ -0,0 +1,103 @@
# fusion_accounting_bank_rec — Cursor / Claude Context
## Purpose
Replaces (or augments — coexists with) Odoo Enterprise's `account_accountant`
bank reconciliation widget with a Fusion-native, AI-assistive implementation.
Ships in Phase 1 of the fusion_accounting roadmap.
## Architecture
Hybrid: the engine (`fusion.reconcile.engine`, AbstractModel) is the SINGLE
write surface for reconciliations. Everything else (controller, OWL widget,
AI tools, wizards, cron) routes through the engine's 6-method API:
- `reconcile_one(line, against_lines, write_off_vals=None)`
- `reconcile_batch(lines, strategy='auto')`
- `suggest_matches(lines, limit_per_line=3)`
- `accept_suggestion(suggestion)`
- `write_off(line, account, amount, label, tax_id=None)`
- `unreconcile(partial_reconciles)`
Pure-Python services live in `services/`:
- `memo_tokenizer` — Canadian bank memo regex
- `exchange_diff` — FX gain/loss pre-compute
- `matching_strategies` — AmountExact, FIFO, MultiInvoice
- `precedent_lookup` — K-nearest search
- `pattern_extractor` — per-partner aggregate
- `confidence_scoring` — 4-pass pipeline (statistical → AI re-rank)
- `precedent_backfill` — migration helper
Persistent models in `models/`:
- `fusion.reconcile.pattern` — per-(company, partner) learned profile
- `fusion.reconcile.precedent` — per-decision history
- `fusion.reconcile.suggestion` — AI suggestions with state lifecycle
- `fusion.bank.rec.widget` — TransientModel for OWL round-trip
- `fusion.unreconciled.bank.line.mv` — pre-aggregated MV for fast UI listing
- `fusion.bank.rec.cron` — cron handler (suggest, pattern refresh, MV refresh)
- `fusion.auto.reconcile.wizard` / `fusion.bulk.reconcile.wizard` — TransientModel wizards
- `fusion.migration.wizard` (inherits) — adds `_bank_rec_bootstrap_step`
- `account.bank.statement.line` (inherits) — adds fusion_top_suggestion_id, fusion_confidence_band, etc.
- `account.reconcile.model` (inherits) — adds fusion_ai_confidence_threshold
Controller: `controllers/bank_rec_controller.py` exposes 10 JSON-RPC endpoints
under `/fusion/bank_rec/*`. All calls route through the engine.
OWL frontend: `static/src/`
- `services/bank_reconciliation_service.js` — central reactive state + RPC wrappers
- `views/kanban/bank_rec_kanban_*.js` — top-level controller + renderer
- `components/bank_reconciliation/<...>` — 14 mirrored Enterprise components + 8 fusion-only components (ai_suggestion folder, batch_action_bar, reconcile_model_picker, attachment_strip, partner_history_panel)
- `tours/bank_rec_tours.js` — 5 OWL tour smoke tests
## Conventions
- **V19 deprecations to avoid:** `_sql_constraints` (use `models.Constraint`),
`@api.depends('id')` (raises `NotImplementedError`), `@route(type='json')`
(use `type='jsonrpc'`), `numbercall` field on `ir.cron` (removed),
`groups_id` on `res.users` (use `all_group_ids` for searching),
`users` field on `res.groups` (use `user_ids`), `groups_id` on
`ir.ui.menu` (use `group_ids`).
- **Coexistence:** When `account_accountant` is installed, the fusion menu
is hidden via `fusion_accounting_core.group_fusion_show_when_enterprise_absent`
(a computed group). Engine model is always available.
- **Materialized view refresh:** Triggered on `fusion.reconcile.suggestion`
create/write (best-effort, non-blocking). Cron refreshes every 5 min via
a dedicated autocommit cursor (REFRESH CONCURRENTLY can't run inside
Odoo's regular transaction).
- **Test factories:** `tests/_factories.py` provides `make_bank_journal`,
`make_bank_line`, `make_invoice`, `make_reconcileable_pair`, `make_suggestion`,
`make_pattern`, `make_precedent`. NOTE: `make_bank_journal` defaults to
code `'TEST'` so multiple calls in one test will collide; pass an explicit
unique code or share a journal across calls.
- **Hypothesis property tests:** Use `@settings(suppress_health_check=[...])`
to silence function_scoped_fixture warnings in TransactionCase.
## Test counts (as of Phase 1 complete)
- 157 logical tests total in fusion_accounting_bank_rec
- 0 failures, 0 errors
- Includes: 4 benchmark tests (tagged 'benchmark'), 1 local LLM smoke (tagged 'local_llm', skips when no LLM), 5 OWL tour tests (tagged 'tour')
## Performance baseline
| Operation | P95 | Budget |
|---|---|---|
| `engine.suggest_matches` (1 line) | 234ms | <500ms |
| `engine.reconcile_batch` (50 lines) | 3318ms | <5000ms |
| `controller.list_unreconciled` (50 lines) | 77ms | <200ms |
| MV refresh | 60ms | <2000ms |
All within 1x of budget at Phase 1 ship.
## Known concerns / Phase 1.5 backlog
- `accept_suggestion` returns `partial_ids` but not `is_reconciled` — UI reads it post-call
- `engine.write_off` mixed mode (write-off + against_lines) implemented but untested
- `engine.reconcile_one` returns `exchange_diff_move_id: None` (Odoo's reconcile() handles FX inline; surfacing the move_id needs an extra query)
- `against_lines` early-break in `reconcile_one` silently drops excess; auto strategy avoids this but manual callers should pre-validate
- Reconcile-model bulk wizard `_apply_lines_for_bank_statement_line` is Enterprise-only (Community falls back to per-line error)
- OWL tour tests skip-mode when websocket-client absent

View File

@@ -0,0 +1,41 @@
# fusion_accounting_bank_rec
AI-assisted bank reconciliation for Odoo 19 Community — a Fusion-native
replacement for Enterprise's `account_accountant` bank reconciliation widget.
## What it does
- Side-by-side parity with Enterprise's bank reconciliation UI (kanban + side
panel, multi-currency, write-offs, attachments, chatter)
- AI-assistive: confidence-scored suggestions per bank line via the
`fusion.reconcile.engine` 4-pass scoring pipeline (statistical + optional
LLM re-rank)
- Coexists with `account_accountant` (Enterprise wins by default; Fusion menu
appears only when Enterprise is uninstalled)
- Migration-aware: bootstrap step backfills `fusion.reconcile.precedent` from
existing `account.partial.reconcile` rows so the AI has memory from day 1
## Quick start
```bash
# Install
odoo --addons-path=... -i fusion_accounting_bank_rec
# Open the widget (when Enterprise's account_accountant is NOT installed)
# Apps → Bank Reconciliation → Reconcile Bank Lines
# When Enterprise IS installed: use Enterprise's UI; the engine + AI tools
# are still available via the AI chat.
```
## Configuration
- Local LLM (LM Studio, Ollama):
- `fusion_accounting.openai_base_url` = `http://host.docker.internal:1234/v1`
- `fusion_accounting.openai_model` = your local model name
- `fusion_accounting.provider.bank_rec_suggest` = `openai`
## See also
- `CLAUDE.md` — agent context
- `UPGRADE_NOTES.md` — Odoo version anchoring

View File

@@ -0,0 +1,34 @@
# fusion_accounting_bank_rec — Upgrade Notes
## Odoo Version Anchor
This module targets **Odoo 19.0** (community-base).
Reference snapshot of Enterprise code mirrored from:
- `account_accountant` (Odoo 19.0.x)
- Source: `/Users/gurpreet/Github/RePackaged-Odoo/accounting/account_accountant/`
## Cross-Version Diff Strategy
When a new Odoo version ships:
1. Run `check_odoo_diff.sh` (in repo root) against the new Enterprise version
2. Note any breaking changes in `account.bank.statement.line` API
3. For mirrored OWL components, diff Enterprise's new versions against ours and
port material changes (signature renames, new behaviour we want to inherit)
4. Re-run the full test suite + tour tests against the new Odoo version
5. Update this file with the new version anchor + any deviations
## V19 Migration Notes (already applied)
- `_sql_constraints``models.Constraint` (Tasks 14, 15)
- `@api.depends('id')` → removed (Task 17)
- `@route(type='json')``type='jsonrpc'` (Task 26)
- `numbercall` removed from `ir.cron` (Task 25)
- `res.groups.users``user_ids` (Task 43)
- `ir.ui.menu.groups_id``group_ids` (Tasks 42, 43)
## Phase 1 → Phase 1.5 Migration
If we ship Phase 1.5 (UI polish, deferred features), changes will go in
incremental commits. No DB migration needed (Phase 1 schema is forward-compatible).

View File

@@ -0,0 +1,5 @@
from . import models
from . import controllers
from . import services
from . import wizards
from . import reports

View File

@@ -0,0 +1,112 @@
{
'name': 'Fusion Accounting — Bank Reconciliation',
'version': '19.0.1.1.1',
'category': 'Accounting/Accounting',
'sequence': 28,
'summary': 'Native V19 bank reconciliation widget with AI confidence scoring + behavioural learning.',
'description': """
Fusion Accounting — Bank Reconciliation
========================================
Replaces Odoo Enterprise's account_accountant bank-rec widget with a
native V19 OWL implementation reading/writing Community's
account.partial.reconcile tables.
Features:
- Strict mirror of all Enterprise UI components (zero functional loss)
- AI confidence badges with one-click Accept and ranked alternatives
- Behavioural learning from historical reconciliations
- Local LLM ready (Ollama, LM Studio) via OpenAI-compatible adapter
- Coexists with account_accountant (Enterprise wins by default)
Built by Nexa Systems Inc.
""",
'icon': '/fusion_accounting_bank_rec/static/description/icon.png',
'author': 'Nexa Systems Inc.',
'website': 'https://nexasystems.ca',
'maintainer': 'Nexa Systems Inc.',
'depends': ['fusion_accounting_core', 'fusion_accounting_migration'],
'external_dependencies': {
'python': ['hypothesis'],
},
'data': [
'security/ir.model.access.csv',
'data/cron.xml',
'wizards/auto_reconcile_wizard_views.xml',
'wizards/bulk_reconcile_wizard_views.xml',
'reports/migration_audit_report_views.xml',
'reports/migration_audit_report_action.xml',
'views/menu_views.xml',
],
'assets': {
'web.assets_backend': [
'fusion_accounting_bank_rec/static/src/scss/_variables.scss',
'fusion_accounting_bank_rec/static/src/scss/bank_reconciliation.scss',
'fusion_accounting_bank_rec/static/src/scss/ai_suggestion.scss',
'fusion_accounting_bank_rec/static/src/services/bank_reconciliation_service.js',
'fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_controller.js',
'fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_renderer.js',
'fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_view.js',
'fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban.xml',
# OWL component mirror — Enterprise account_accountant bank-rec.
# Re-export shim so mirrored components can use the relative
# `../bank_reconciliation_service` import unchanged.
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/bank_reconciliation_service.js',
# Batch 1 (Task 30) — display components
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/statement_line/statement_line.js',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/statement_line/statement_line.xml',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/statement_summary/statement_summary.js',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/statement_summary/statement_summary.xml',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/line_info_pop_over/line_info_pop_over.js',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/line_info_pop_over/line_info_pop_over.xml',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/reconciled_line_name/reconciled_line_name.js',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/reconciled_line_name/reconciled_line_name.xml',
# Batch 2 (Task 31) — action + edit components
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/button/button.js',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/button/button.xml',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/button_list/button_list.js',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/button_list/button_list.xml',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/line_to_reconcile/line_to_reconcile.js',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/line_to_reconcile/line_to_reconcile.xml',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/list_view/list.js',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/list_view/list_view_many2one_multi_edit.js',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/list_view/list_view_many2one_multi_edit.xml',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/apply_amount/apply_amount.js',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/apply_amount/apply_amount.xml',
# Batch 3 (Task 32) — dialog components
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/bankrec_form_dialog/bankrec_form_dialog.js',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/bankrec_form_dialog/bankrec_form_dialog.xml',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/search_dialog/search_dialog.js',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/search_dialog/search_dialog.xml',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/search_dialog/search_dialog_list.js',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/search_dialog/search_dialog_list.xml',
# Batch 4 (Task 33) — auxiliary components
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/quick_create/quick_create.js',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/quick_create/quick_create.xml',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/chatter/chatter.js',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/file_uploader/file_uploader.js',
# Fusion-only (Task 34) — AI suggestion UI
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/ai_suggestion/ai_suggestion_strip.js',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/ai_suggestion/ai_suggestion_strip.xml',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/ai_suggestion/ai_alternatives_panel.js',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/ai_suggestion/ai_alternatives_panel.xml',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/ai_suggestion/ai_reasoning_tooltip.js',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/ai_suggestion/ai_reasoning_tooltip.xml',
# Fusion-only (Task 35) — batch action bar + reconcile model picker
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/batch_action_bar/batch_action_bar.js',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/batch_action_bar/batch_action_bar.xml',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/reconcile_model_picker/reconcile_model_picker.js',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/reconcile_model_picker/reconcile_model_picker.xml',
# Fusion-only (Task 36) — attachment strip + partner history panel
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/attachment_strip/attachment_strip.js',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/attachment_strip/attachment_strip.xml',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/partner_history_panel/partner_history_panel.js',
'fusion_accounting_bank_rec/static/src/components/bank_reconciliation/partner_history_panel/partner_history_panel.xml',
],
'web.assets_tests': [
'fusion_accounting_bank_rec/static/src/tours/bank_rec_tours.js',
],
},
'installable': True,
'application': False,
'license': 'OPL-1',
}

View File

@@ -0,0 +1 @@
from . import bank_rec_controller

View File

@@ -0,0 +1,325 @@
"""HTTP controller: 10 JSON-RPC endpoints for the OWL bank-rec widget.
All endpoints route through ``BankRecAdapter`` (which lives in
``fusion_accounting_ai`` and already encapsulates fusion / enterprise /
community routing) or directly through ``fusion.reconcile.engine`` for
methods the adapter does not yet expose. The controller never touches
``account.partial.reconcile`` directly.
V19: uses ``@route(type='jsonrpc')``, the V19-blessed replacement for the
deprecated ``type='json'`` (Odoo 19 logs a deprecation warning if you
still use ``json``).
"""
import logging
from odoo import _, http
from odoo.exceptions import ValidationError
from odoo.http import request
_logger = logging.getLogger(__name__)
def _adapter():
"""Resolve the bank-rec data adapter from fusion_accounting_ai."""
from odoo.addons.fusion_accounting_ai.services.data_adapters import (
get_adapter,
)
return get_adapter(request.env, 'bank_rec')
class FusionBankRecController(http.Controller):
"""JSON-RPC surface consumed by the OWL bank-reconciliation widget.
All routes are ``auth='user'`` -- anonymous traffic is rejected by
Odoo's HTTP layer before reaching the handler.
"""
# ------------------------------------------------------------------
# 1. get_state -- initial widget bootstrap
# ------------------------------------------------------------------
@http.route('/fusion/bank_rec/get_state', type='jsonrpc', auth='user')
def get_state(self, journal_id, company_id):
"""Return the journal summary that seeds the kanban widget."""
Journal = request.env['account.journal']
Line = request.env['account.bank.statement.line']
journal = Journal.browse(int(journal_id))
if not journal.exists():
raise ValidationError(_("Journal %s not found") % journal_id)
company_id = int(company_id) if company_id else request.env.company.id
unreconciled_lines = Line.search([
('journal_id', '=', journal.id),
('is_reconciled', '=', False),
('company_id', '=', company_id),
])
total_amount = sum(abs(l.amount) for l in unreconciled_lines)
last_stmt = request.env['account.bank.statement'].search(
[('journal_id', '=', journal.id)],
order='date desc', limit=1)
currency = journal.currency_id or journal.company_id.currency_id
return {
'journal': {
'id': journal.id,
'name': journal.name,
'currency_code': currency.name,
},
'unreconciled_count': len(unreconciled_lines),
'total_pending_amount': total_amount,
'last_statement_date': str(last_stmt.date) if last_stmt and last_stmt.date else None,
}
# ------------------------------------------------------------------
# 2. list_unreconciled -- paginated, fusion-enriched
# ------------------------------------------------------------------
@http.route('/fusion/bank_rec/list_unreconciled', type='jsonrpc', auth='user')
def list_unreconciled(self, journal_id, limit=50, offset=0,
company_id=None, date_from=None, date_to=None,
min_amount=None):
"""Return enriched, paginated unreconciled bank lines."""
limit = int(limit)
offset = int(offset)
company_id = (int(company_id) if company_id
else request.env.company.id)
# The adapter doesn't take an offset; over-fetch and slice.
rows = _adapter().list_unreconciled(
journal_id=int(journal_id),
limit=limit + offset,
company_id=company_id,
date_from=date_from,
date_to=date_to,
min_amount=min_amount,
)
sliced = rows[offset:offset + limit]
Line = request.env['account.bank.statement.line']
domain = [
('journal_id', '=', int(journal_id)),
('is_reconciled', '=', False),
('company_id', '=', company_id),
]
if date_from:
domain.append(('date', '>=', date_from))
if date_to:
domain.append(('date', '<=', date_to))
if min_amount is not None:
domain.append(('amount', '>=', float(min_amount)))
total = Line.search_count(domain)
return {
'count': len(sliced),
'total': total,
'lines': sliced,
}
# ------------------------------------------------------------------
# 3. get_line_detail -- one line + suggestions + attachments
# ------------------------------------------------------------------
@http.route('/fusion/bank_rec/get_line_detail', type='jsonrpc', auth='user')
def get_line_detail(self, statement_line_id):
"""Return full detail for one line including pending suggestions."""
Line = request.env['account.bank.statement.line']
line = Line.browse(int(statement_line_id))
if not line.exists():
raise ValidationError(
_("Statement line %s not found") % statement_line_id)
Sug = request.env['fusion.reconcile.suggestion']
suggestions = Sug.search([
('statement_line_id', '=', line.id),
('state', '=', 'pending'),
], order='confidence desc, rank asc')
Att = request.env['ir.attachment']
attachments = Att.search([
('res_model', '=', 'account.move'),
('res_id', '=', line.move_id.id),
]) if line.move_id else Att.browse()
currency = line.currency_id or line.company_id.currency_id
return {
'line': {
'id': line.id,
'date': str(line.date) if line.date else None,
'payment_ref': line.payment_ref or '',
'amount': line.amount,
'partner_id': line.partner_id.id if line.partner_id else None,
'partner_name': line.partner_id.name if line.partner_id else None,
'currency_id': currency.id,
'currency_code': currency.name,
'journal_id': line.journal_id.id,
'journal_name': line.journal_id.name,
'is_reconciled': line.is_reconciled,
},
'suggestions': [{
'id': s.id,
'candidate_ids': s.proposed_move_line_ids.ids,
'confidence': s.confidence,
'rank': s.rank,
'reasoning': s.reasoning or '',
'scores': {
'amount_match': s.score_amount_match,
'partner_pattern': s.score_partner_pattern,
'precedent_similarity': s.score_precedent_similarity,
'ai_rerank': s.score_ai_rerank,
},
} for s in suggestions],
'attachments': [{
'id': a.id,
'name': a.name,
'mimetype': a.mimetype,
} for a in attachments],
}
# ------------------------------------------------------------------
# 4. suggest_matches -- lazy AI suggest for a line
# ------------------------------------------------------------------
@http.route('/fusion/bank_rec/suggest_matches', type='jsonrpc', auth='user')
def suggest_matches(self, statement_line_ids, limit_per_line=3):
"""Trigger AI suggest for one or more statement lines."""
ids = [int(i) for i in (statement_line_ids or [])]
result = _adapter().suggest_matches(
statement_line_ids=ids,
limit_per_line=int(limit_per_line),
)
return {'suggestions': result}
# ------------------------------------------------------------------
# 5. accept_suggestion -- promote AI suggestion to real reconcile
# ------------------------------------------------------------------
@http.route('/fusion/bank_rec/accept_suggestion', type='jsonrpc', auth='user')
def accept_suggestion(self, suggestion_id):
"""Accept a fusion suggestion. Returns the partial IDs created."""
sug = request.env['fusion.reconcile.suggestion'].browse(
int(suggestion_id))
if not sug.exists():
raise ValidationError(
_("Suggestion %s not found") % suggestion_id)
# Capture the journal/company before reconcile (the sug may go stale).
journal_id = sug.statement_line_id.journal_id.id
company_id = sug.company_id.id
result = _adapter().accept_suggestion(suggestion_id=int(suggestion_id))
unreconciled_count_after = request.env[
'account.bank.statement.line'].search_count([
('journal_id', '=', journal_id),
('is_reconciled', '=', False),
('company_id', '=', company_id),
])
return {
'status': 'accepted',
'partial_ids': result.get('partial_ids', []),
'unreconciled_count_after': unreconciled_count_after,
}
# ------------------------------------------------------------------
# 6. reconcile_manual -- user picked candidates manually
# ------------------------------------------------------------------
@http.route('/fusion/bank_rec/reconcile_manual', type='jsonrpc', auth='user')
def reconcile_manual(self, statement_line_id, against_move_line_ids):
"""Reconcile a line against an explicit set of journal items."""
line = request.env['account.bank.statement.line'].browse(
int(statement_line_id))
if not line.exists():
raise ValidationError(
_("Statement line %s not found") % statement_line_id)
cands = request.env['account.move.line'].browse(
[int(i) for i in (against_move_line_ids or [])])
result = request.env['fusion.reconcile.engine'].reconcile_one(
line, against_lines=cands)
return {
'status': 'reconciled',
'partial_ids': result.get('partial_ids', []),
}
# ------------------------------------------------------------------
# 7. unreconcile -- reverse a prior reconcile
# ------------------------------------------------------------------
@http.route('/fusion/bank_rec/unreconcile', type='jsonrpc', auth='user')
def unreconcile(self, partial_reconcile_ids):
"""Reverse one or more partial reconciles."""
ids = [int(i) for i in (partial_reconcile_ids or [])]
result = _adapter().unreconcile(partial_reconcile_ids=ids)
return {
'status': 'unreconciled',
'unreconciled_line_ids': result.get('unreconciled_line_ids', []),
}
# ------------------------------------------------------------------
# 8. write_off -- absorb residual into a write-off account
# ------------------------------------------------------------------
@http.route('/fusion/bank_rec/write_off', type='jsonrpc', auth='user')
def write_off(self, statement_line_id, account_id, amount, label,
tax_id=None):
"""Apply a write-off against a bank statement line."""
line = request.env['account.bank.statement.line'].browse(
int(statement_line_id))
if not line.exists():
raise ValidationError(
_("Statement line %s not found") % statement_line_id)
account = request.env['account.account'].browse(int(account_id))
tax = (request.env['account.tax'].browse(int(tax_id))
if tax_id else None)
result = request.env['fusion.reconcile.engine'].write_off(
line, account=account, amount=float(amount),
tax_id=tax, label=label)
return {
'status': 'written_off',
'partial_ids': result.get('partial_ids', []),
'write_off_move_id': result.get('write_off_move_id'),
}
# ------------------------------------------------------------------
# 9. bulk_reconcile -- batch auto-reconcile a recordset
# ------------------------------------------------------------------
@http.route('/fusion/bank_rec/bulk_reconcile', type='jsonrpc', auth='user')
def bulk_reconcile(self, statement_line_ids, strategy='auto'):
"""Batch auto-reconcile. Returns counts + per-line errors."""
ids = [int(i) for i in (statement_line_ids or [])]
lines = request.env['account.bank.statement.line'].browse(ids)
result = request.env['fusion.reconcile.engine'].reconcile_batch(
lines, strategy=strategy)
return result
# ------------------------------------------------------------------
# 10. get_partner_history -- partner reconcile history panel
# ------------------------------------------------------------------
@http.route('/fusion/bank_rec/get_partner_history', type='jsonrpc', auth='user')
def get_partner_history(self, partner_id, limit=20):
"""Return a partner's reconcile history + learned pattern."""
Partner = request.env['res.partner']
partner = Partner.browse(int(partner_id))
if not partner.exists():
raise ValidationError(_("Partner %s not found") % partner_id)
Precedent = request.env['fusion.reconcile.precedent']
recent = Precedent.search(
[('partner_id', '=', partner.id)],
order='reconciled_at desc, id desc',
limit=int(limit),
)
Pattern = request.env['fusion.reconcile.pattern']
pattern = Pattern.search(
[('partner_id', '=', partner.id)], limit=1)
return {
'partner': {
'id': partner.id,
'name': partner.name,
},
'recent_reconciles': [{
'precedent_id': p.id,
'date': str(p.date) if p.date else None,
'amount': p.amount,
'memo_tokens': p.memo_tokens or '',
'matched_count': p.matched_move_line_count,
'source': p.source,
} for p in recent],
'pattern': ({
'reconcile_count': pattern.reconcile_count,
'pref_strategy': pattern.pref_strategy or None,
'common_memo_tokens': pattern.common_memo_tokens or None,
'typical_cadence_days': pattern.typical_cadence_days,
} if pattern else None),
}

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo noupdate="1">
<record id="cron_fusion_bank_rec_suggest" model="ir.cron">
<field name="name">Fusion Bank Rec — Warm AI Suggestions</field>
<field name="model_id" ref="model_fusion_bank_rec_cron"/>
<field name="state">code</field>
<field name="code">model._cron_suggest_pending()</field>
<field name="interval_number">30</field>
<field name="interval_type">minutes</field>
<field name="active" eval="True"/>
</record>
<record id="cron_fusion_bank_rec_pattern_refresh" model="ir.cron">
<field name="name">Fusion Bank Rec — Refresh Partner Patterns</field>
<field name="model_id" ref="model_fusion_bank_rec_cron"/>
<field name="state">code</field>
<field name="code">model._cron_refresh_patterns()</field>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="nextcall" eval="(DateTime.now().replace(hour=2, minute=0, second=0) + timedelta(days=1)).strftime('%Y-%m-%d %H:%M:%S')"/>
<field name="active" eval="True"/>
</record>
<record id="cron_fusion_bank_rec_mv_refresh" model="ir.cron">
<field name="name">Fusion Bank Rec — Refresh Unreconciled MV</field>
<field name="model_id" ref="model_fusion_bank_rec_cron"/>
<field name="state">code</field>
<field name="code">model._cron_refresh_mv()</field>
<field name="interval_number">5</field>
<field name="interval_type">minutes</field>
<field name="active" eval="True"/>
</record>
</odoo>

View File

@@ -0,0 +1,57 @@
-- Materialized view: pre-aggregated data for the OWL bank reconciliation widget.
-- Refreshed on cron (Task 25) and on suggestion writes.
-- Indexed on (company_id, journal_id, date) for fast UI queries.
-- NOTE: account_bank_statement_line does not store `date` directly in V19;
-- it is a related field through move_id -> account_move.date. We JOIN on
-- account_move to get it.
CREATE MATERIALIZED VIEW IF NOT EXISTS fusion_unreconciled_bank_line_mv AS
SELECT
bsl.id AS id,
bsl.company_id AS company_id,
bsl.journal_id AS journal_id,
am.date AS date,
bsl.amount AS amount,
bsl.payment_ref AS payment_ref,
bsl.currency_id AS currency_id,
bsl.partner_id AS partner_id,
bsl.create_date AS create_date,
-- Top suggestion (highest confidence pending one)
(SELECT s.id FROM fusion_reconcile_suggestion s
WHERE s.statement_line_id = bsl.id AND s.state = 'pending'
ORDER BY s.confidence DESC, s.rank ASC LIMIT 1) AS top_suggestion_id,
(SELECT s.confidence FROM fusion_reconcile_suggestion s
WHERE s.statement_line_id = bsl.id AND s.state = 'pending'
ORDER BY s.confidence DESC, s.rank ASC LIMIT 1) AS top_confidence,
CASE
WHEN (SELECT MAX(s.confidence) FROM fusion_reconcile_suggestion s
WHERE s.statement_line_id = bsl.id AND s.state = 'pending') >= 0.85
THEN 'high'
WHEN (SELECT MAX(s.confidence) FROM fusion_reconcile_suggestion s
WHERE s.statement_line_id = bsl.id AND s.state = 'pending') >= 0.60
THEN 'medium'
WHEN (SELECT MAX(s.confidence) FROM fusion_reconcile_suggestion s
WHERE s.statement_line_id = bsl.id AND s.state = 'pending') > 0
THEN 'low'
ELSE 'none'
END AS confidence_band,
-- Attachment count (assumes ir_attachment.res_model='account.bank.statement.line')
(SELECT COUNT(*) FROM ir_attachment att
WHERE att.res_model = 'account.bank.statement.line' AND att.res_id = bsl.id)
AS attachment_count,
-- Partner reconcile pattern hint
COALESCE((SELECT p.reconcile_count FROM fusion_reconcile_pattern p
WHERE p.partner_id = bsl.partner_id AND p.company_id = bsl.company_id LIMIT 1), 0)
AS partner_reconcile_count
FROM account_bank_statement_line bsl
JOIN account_move am ON am.id = bsl.move_id
WHERE bsl.is_reconciled IS NOT TRUE;
-- Indexes for the common UI queries: filter by company + journal, sort by date desc.
CREATE INDEX IF NOT EXISTS fusion_mv_unrec_company_journal_date_idx
ON fusion_unreconciled_bank_line_mv (company_id, journal_id, date DESC);
CREATE INDEX IF NOT EXISTS fusion_mv_unrec_partner_idx
ON fusion_unreconciled_bank_line_mv (partner_id) WHERE partner_id IS NOT NULL;
-- UNIQUE index required for CONCURRENTLY refresh
CREATE UNIQUE INDEX IF NOT EXISTS fusion_mv_unrec_id_idx
ON fusion_unreconciled_bank_line_mv (id);

View File

@@ -0,0 +1,176 @@
from datetime import date
from odoo import api, Command, fields, models, _
from odoo.exceptions import UserError
class AccountAutoReconcileWizard(models.TransientModel):
""" This wizard is used to automatically reconcile account.move.line.
It is accessible trough Accounting > Accounting tab > Actions > Auto-reconcile menuitem.
"""
_name = 'account.auto.reconcile.wizard'
_description = 'Account automatic reconciliation wizard'
_check_company_auto = True
company_id = fields.Many2one(
comodel_name='res.company',
required=True,
readonly=True,
default=lambda self: self.env.company,
)
line_ids = fields.Many2many(comodel_name='account.move.line') # Amls from which we derive a preset for the wizard
from_date = fields.Date(string='From')
to_date = fields.Date(string='To', default=fields.Date.context_today, required=True)
account_ids = fields.Many2many(
comodel_name='account.account',
string='Accounts',
check_company=True,
domain="[('reconcile', '=', True), ('account_type', '!=', 'off_balance')]",
)
partner_ids = fields.Many2many(
comodel_name='res.partner',
string='Partners',
check_company=True,
domain="[('company_id', 'in', (False, company_id)), '|', ('parent_id', '=', False), ('is_company', '=', True)]",
)
search_mode = fields.Selection(
selection=[
('one_to_one', "Perfect Match"),
('zero_balance', "Clear Account"),
],
string='Reconcile',
required=True,
default='one_to_one',
help="Reconcile journal items with opposite balance or clear accounts with a zero balance",
)
@api.model
def default_get(self, fields):
res = super().default_get(fields)
domain = self.env.context.get('domain')
if 'line_ids' in fields and 'line_ids' not in res and domain:
amls = self.env['account.move.line'].search(domain)
if amls:
# pre-configure the wizard
res.update(self._get_default_wizard_values(amls))
res['line_ids'] = [Command.set(amls.ids)]
return res
@api.model
def _get_default_wizard_values(self, amls):
""" Derive a preset configuration based on amls.
For example if all amls have the same account_id we will set it in the wizard.
:param amls: account move lines from which we will derive a preset
:return: a dict with preset values
"""
return {
'account_ids': [Command.set(amls[0].account_id.ids)] if all(aml.account_id == amls[0].account_id for aml in amls) else [],
'partner_ids': [Command.set(amls[0].partner_id.ids)] if all(aml.partner_id == amls[0].partner_id for aml in amls) else [],
'search_mode': 'zero_balance' if amls.company_currency_id.is_zero(sum(amls.mapped('balance'))) else 'one_to_one',
'from_date': min(amls.mapped('date')),
'to_date': max(amls.mapped('date')),
}
def _get_wizard_values(self):
""" Get the current configuration of the wizard as a dict of values.
:return: a dict with the current configuration of the wizard.
"""
self.ensure_one()
return {
'account_ids': [Command.set(self.account_ids.ids)] if self.account_ids else [],
'partner_ids': [Command.set(self.partner_ids.ids)] if self.partner_ids else [],
'search_mode': self.search_mode,
'from_date': self.from_date,
'to_date': self.to_date,
}
# ==== Business methods ====
def _get_amls_domain(self):
""" Get the domain of amls to be auto-reconciled. """
self.ensure_one()
if self.line_ids and self._get_wizard_values() == self._get_default_wizard_values(self.line_ids):
domain = [('id', 'in', self.line_ids.ids)]
else:
domain = [
('company_id', '=', self.company_id.id),
('parent_state', '=', 'posted'),
('display_type', 'not in', ('line_section', 'line_subsection', 'line_note')),
('date', '>=', self.from_date or date.min),
('date', '<=', self.to_date),
('reconciled', '=', False),
('account_id.reconcile', '=', True),
('amount_residual_currency', '!=', 0.0),
('amount_residual', '!=', 0.0), # excludes exchange difference lines
]
if self.account_ids:
domain.append(('account_id', 'in', self.account_ids.ids))
if self.partner_ids:
domain.append(('partner_id', 'in', self.partner_ids.ids))
return domain
def _auto_reconcile_one_to_one(self):
""" Auto-reconcile with one-to-one strategy:
We will reconcile 2 amls together if their combined balance is zero.
:return: a recordset of reconciled amls
"""
grouped_amls_data = self.env['account.move.line']._read_group(
self._get_amls_domain(),
['account_id', 'partner_id', 'currency_id', 'amount_residual_currency:abs_rounded'],
['id:recordset'],
)
all_reconciled_amls = self.env['account.move.line']
amls_grouped_by_2 = [] # we need to group amls with right format for _reconcile_plan
for *__, grouped_aml_ids in grouped_amls_data:
positive_amls = grouped_aml_ids.filtered(lambda aml: aml.amount_residual_currency >= 0).sorted('date')
negative_amls = (grouped_aml_ids - positive_amls).sorted('date')
min_len = min(len(positive_amls), len(negative_amls))
positive_amls = positive_amls[:min_len]
negative_amls = negative_amls[:min_len]
all_reconciled_amls += positive_amls + negative_amls
amls_grouped_by_2 += [pos_aml + neg_aml for (pos_aml, neg_aml) in zip(positive_amls, negative_amls)]
self.env['account.move.line']._reconcile_plan(amls_grouped_by_2)
return all_reconciled_amls
def _auto_reconcile_zero_balance(self):
""" Auto-reconcile with zero balance strategy:
We will reconcile all amls grouped by currency/account/partner that have a total balance of zero.
:return: a recordset of reconciled amls
"""
grouped_amls_data = self.env['account.move.line']._read_group(
self._get_amls_domain(),
groupby=['account_id', 'partner_id', 'currency_id'],
aggregates=['id:recordset'],
having=[('amount_residual_currency:sum_rounded', '=', 0)],
)
all_reconciled_amls = self.env['account.move.line']
amls_grouped_together = [] # we need to group amls with right format for _reconcile_plan
for aml_data in grouped_amls_data:
all_reconciled_amls += aml_data[-1]
amls_grouped_together += [aml_data[-1]]
self.env['account.move.line']._reconcile_plan(amls_grouped_together)
return all_reconciled_amls
def auto_reconcile(self):
""" Automatically reconcile amls given wizard's parameters.
:return: an action that opens all reconciled items and related amls (exchange diff, etc)
"""
self.ensure_one()
if self.search_mode == 'zero_balance':
reconciled_amls = self._auto_reconcile_zero_balance()
else:
# search_mode == 'one_to_one'
reconciled_amls = self._auto_reconcile_one_to_one()
reconciled_amls_and_related = self.env['account.move.line'].search([
('full_reconcile_id', 'in', reconciled_amls.full_reconcile_id.ids)
])
if reconciled_amls_and_related:
return {
'name': _("Automatically Reconciled Entries"),
'type': 'ir.actions.act_window',
'res_model': 'account.move.line',
'context': "{'search_default_group_by_matching': True}",
'view_mode': 'list',
'domain': [('id', 'in', reconciled_amls_and_related.ids)],
}
else:
raise UserError(self.env._("Nothing to reconcile."))

View File

@@ -0,0 +1,325 @@
from odoo import SUPERUSER_ID, api, fields, models
from odoo.tools import SQL
class AccountReconcileModel(models.Model):
_inherit = 'account.reconcile.model'
# Technical field to know if the rule was created automatically or by a user.
created_automatically = fields.Boolean(default=False, copy=False)
def _apply_lines_for_bank_widget(self, residual_amount_currency, residual_balance, partner, st_line):
""" Apply the reconciliation model lines to the statement line passed as parameter.
:param residual_amount_currency: The open amount currency of the statement line in the bank reconciliation widget
expressed in the statement line currency.
:param residual_balance: The open balance of the statement line in the bank reconciliation widget
expressed in the company currency.
:param partner: The partner set on the wizard.
:param st_line: The statement line processed by the bank reconciliation widget.
:return: A list of python dictionaries (one per reconcile model line) representing
the journal items to be created by the current reconcile model.
"""
self.ensure_one()
currency = st_line.foreign_currency_id or st_line.journal_id.currency_id or st_line.company_currency_id
vals_list = []
for line in self.line_ids:
vals = line._apply_in_bank_widget(
residual_amount_currency=residual_amount_currency,
residual_balance=residual_balance,
partner=line.partner_id or partner,
st_line=st_line,
)
amount_currency = vals['amount_currency']
balance = vals['balance']
if currency.is_zero(amount_currency) and st_line.company_currency_id.is_zero(balance):
continue
vals_list.append(vals)
residual_amount_currency -= amount_currency
residual_balance -= balance
return vals_list
@api.model
def get_available_reconcile_model_per_statement_line(self, statement_line_ids):
self.check_access('read')
self.env['account.reconcile.model'].flush_model()
self.env['account.bank.statement.line'].flush_model()
self.env.cr.execute(SQL(
"""
WITH matching_journal_ids AS (
SELECT account_reconcile_model_id,
ARRAY_AGG(account_journal_id) AS ids
FROM account_journal_account_reconcile_model_rel
GROUP BY account_reconcile_model_id
),
matching_partner_ids AS (
SELECT account_reconcile_model_id,
ARRAY_AGG(res_partner_id) AS ids
FROM account_reconcile_model_res_partner_rel
GROUP BY account_reconcile_model_id
)
SELECT st_line.id AS st_line_id,
array_agg(reco_model.id ORDER BY reco_model.sequence ASC, reco_model.id ASC) AS reco_model_ids,
array_agg(reco_model.name ORDER BY reco_model.sequence ASC, reco_model.id ASC) AS reco_model_names
FROM account_bank_statement_line st_line
LEFT JOIN LATERAL (
SELECT DISTINCT reco_model.id,
reco_model.sequence,
COALESCE(reco_model.name -> %(lang)s, reco_model.name -> 'en_US') as name
FROM account_reconcile_model reco_model
LEFT JOIN matching_journal_ids ON reco_model.id = matching_journal_ids.account_reconcile_model_id
LEFT JOIN matching_partner_ids ON reco_model.id = matching_partner_ids.account_reconcile_model_id
LEFT JOIN account_reconcile_model_line reco_model_line ON reco_model_line.model_id = reco_model.id
WHERE (matching_journal_ids.ids IS NULL OR st_line.journal_id = ANY(matching_journal_ids.ids))
AND (matching_partner_ids.ids IS NULL OR st_line.partner_id = ANY(matching_partner_ids.ids))
AND (
CASE COALESCE(reco_model.match_amount, '')
WHEN 'lower' THEN st_line.amount <= reco_model.match_amount_max
WHEN 'greater' THEN st_line.amount >= reco_model.match_amount_min
WHEN 'between' THEN
(st_line.amount BETWEEN reco_model.match_amount_min AND reco_model.match_amount_max) OR
(st_line.amount BETWEEN reco_model.match_amount_max AND reco_model.match_amount_min)
ELSE TRUE
END
)
AND (
reco_model.match_label IS NULL
OR (
reco_model.match_label = 'contains'
AND (
st_line.payment_ref IS NOT NULL AND st_line.payment_ref ILIKE '%%' || reco_model.match_label_param || '%%'
OR st_line.transaction_details IS NOT NULL AND st_line.transaction_details::TEXT ILIKE '%%' || reco_model.match_label_param || '%%'
)
) OR (
reco_model.match_label = 'not_contains'
AND NOT (
st_line.payment_ref IS NOT NULL AND st_line.payment_ref ILIKE '%%' || reco_model.match_label_param || '%%'
OR st_line.transaction_details IS NOT NULL AND st_line.transaction_details::TEXT ILIKE '%%' || reco_model.match_label_param || '%%'
)
) OR (
reco_model.match_label = 'match_regex'
AND (
st_line.payment_ref IS NOT NULL AND st_line.payment_ref ~* reco_model.match_label_param
OR st_line.transaction_details IS NOT NULL AND st_line.transaction_details::TEXT ~* reco_model.match_label_param
)
)
)
AND reco_model.company_id = st_line.company_id
AND reco_model.trigger = 'manual'
AND reco_model_line.account_id IS NOT NULL
AND reco_model.active IS TRUE
) AS reco_model ON TRUE
WHERE st_line.id IN %(statement_lines)s
AND reco_model.id IS NOT NULL
GROUP BY st_line.id
""",
lang=self.env.lang,
statement_lines=tuple(statement_line_ids),
))
query_result = self.env.cr.fetchall()
return {
st_line_id: [
{'id': model_id, 'display_name': model_name}
for (model_id, model_name)
in zip(model_ids, model_names)
]
for st_line_id, model_ids, model_names
in query_result
}
def _apply_reconcile_models(self, statement_lines):
if not self or not statement_lines:
return
self.env['account.reconcile.model'].flush_model()
statement_lines.flush_recordset(['journal_id', 'amount', 'amount_residual', 'transaction_details', 'payment_ref', 'partner_id', 'company_id'])
self.env.cr.execute(SQL("""
WITH matching_journal_ids AS (
SELECT account_reconcile_model_id,
ARRAY_AGG(account_journal_id) AS ids
FROM account_journal_account_reconcile_model_rel
GROUP BY account_reconcile_model_id
),
matching_partner_ids AS (
SELECT account_reconcile_model_id,
ARRAY_AGG(res_partner_id) AS ids
FROM account_reconcile_model_res_partner_rel
GROUP BY account_reconcile_model_id
),
model_fees AS (
SELECT model_fees.id,
model_fees.trigger,
matching_journal_ids.ids AS journal_ids
FROM account_reconcile_model model_fees
JOIN ir_model_data imd ON model_fees.id = imd.res_id
JOIN account_reconcile_model_line model_lines ON model_lines.model_id = model_fees.id
LEFT JOIN matching_journal_ids ON model_fees.id = matching_journal_ids.account_reconcile_model_id
WHERE imd.module = 'account'
AND imd.name LIKE 'account_reco_model_fee_%%'
AND model_fees.active IS TRUE
AND model_lines.account_id IS NOT NULL
)
SELECT st_line.id AS st_line_id,
COALESCE(reco_model.id, model_fees.id) AS reco_model_id,
COALESCE(reco_model.trigger, model_fees.trigger) AS trigger
FROM account_bank_statement_line st_line
JOIN account_move move ON st_line.move_id = move.id
LEFT JOIN LATERAL (
SELECT reco_model.id,
reco_model.trigger
FROM account_reconcile_model reco_model
LEFT JOIN matching_journal_ids ON reco_model.id = matching_journal_ids.account_reconcile_model_id
LEFT JOIN matching_partner_ids ON reco_model.id = matching_partner_ids.account_reconcile_model_id
WHERE (matching_journal_ids.ids IS NULL OR st_line.journal_id = ANY(matching_journal_ids.ids))
AND (matching_partner_ids.ids IS NULL OR st_line.partner_id = ANY(matching_partner_ids.ids))
AND (
CASE COALESCE(reco_model.match_amount, '')
WHEN 'lower' THEN st_line.amount <= reco_model.match_amount_max
WHEN 'greater' THEN st_line.amount >= reco_model.match_amount_min
WHEN 'between' THEN
(st_line.amount BETWEEN reco_model.match_amount_min AND reco_model.match_amount_max) OR
(st_line.amount BETWEEN reco_model.match_amount_max AND reco_model.match_amount_min)
ELSE TRUE
END
)
AND (
reco_model.match_label IS NULL
OR (
reco_model.match_label = 'contains'
AND (
st_line.payment_ref IS NOT NULL AND st_line.payment_ref ILIKE '%%' || reco_model.match_label_param || '%%'
OR st_line.transaction_details IS NOT NULL AND st_line.transaction_details::TEXT ILIKE '%%' || reco_model.match_label_param || '%%'
OR move.narration IS NOT NULL AND move.narration::TEXT ILIKE '%%' || reco_model.match_label_param || '%%'
)
) OR (
reco_model.match_label = 'not_contains'
AND NOT (
st_line.payment_ref IS NOT NULL AND st_line.payment_ref ILIKE '%%' || reco_model.match_label_param || '%%'
OR st_line.transaction_details IS NOT NULL AND st_line.transaction_details::TEXT ILIKE '%%' || reco_model.match_label_param || '%%'
OR move.narration IS NOT NULL AND move.narration::TEXT ILIKE '%%' || reco_model.match_label_param || '%%'
)
) OR (
reco_model.match_label = 'match_regex'
AND (
st_line.payment_ref IS NOT NULL AND st_line.payment_ref ~* reco_model.match_label_param
OR st_line.transaction_details IS NOT NULL AND st_line.transaction_details::TEXT ~* reco_model.match_label_param
OR move.narration IS NOT NULL AND move.narration::TEXT ~* reco_model.match_label_param
)
)
)
AND reco_model.id IN %s
AND reco_model.can_be_proposed IS TRUE
AND reco_model.company_id = st_line.company_id
ORDER BY reco_model.sequence ASC, reco_model.id ASC
LIMIT 1
) AS reco_model ON TRUE
LEFT JOIN LATERAL (
SELECT model_fees.id,
model_fees.trigger
FROM model_fees
WHERE st_line.journal_id = ANY(model_fees.journal_ids)
-- Show model fees if matched amount was 3 %% higher than incoming statement line amount
AND SIGN(st_line.amount) > 0
AND SIGN(st_line.amount_residual) > 0
AND ABS(st_line.amount_residual) < 0.03 * st_line.amount / 1.03
) AS model_fees ON TRUE
WHERE st_line.id IN %s
""", tuple(self.ids), tuple(statement_lines.ids)))
query_result = self.env.cr.fetchall()
processed_st_line_ids = set()
# apply the found suitable reco models on the statement lines
for st_line_id, reco_model_id, reco_model_trigger in query_result:
if st_line_id in processed_st_line_ids or reco_model_id is None:
continue
st_line = self.env['account.bank.statement.line'].browse(st_line_id).with_prefetch(statement_lines.ids)
reco_model = self.env['account.reconcile.model'].browse(reco_model_id).with_prefetch(self.ids)
if reco_model_trigger == 'manual':
st_line._action_manual_reco_model(reco_model_id)
else:
reco_model.with_user(SUPERUSER_ID)._trigger_reconciliation_model(st_line.with_user(SUPERUSER_ID))
processed_st_line_ids.add(st_line_id)
def _trigger_reconciliation_model(self, statement_line):
self.ensure_one()
liquidity_line, suspense_line, other_lines = statement_line._seek_for_lines()
amls_to_create = list(
self._apply_lines_for_bank_widget(
residual_amount_currency=sum(suspense_line.mapped('amount_currency')),
residual_balance=sum(suspense_line.mapped('balance')),
partner=statement_line.partner_id,
st_line=statement_line,
)
)
# Get the original base lines and tax lines before the creation of new lines
if any(aml.get('tax_ids') for aml in amls_to_create):
original_base_lines, original_tax_lines = statement_line._prepare_for_tax_lines_recomputation()
statement_line._set_move_line_to_statement_line_move(liquidity_line + other_lines, amls_to_create)
# Now that the new lines have been added, we can recompute the taxes
if any(aml.get('tax_ids') for aml in amls_to_create):
_new_liquidity_line, new_suspense_line, _new_other_lines = statement_line._seek_for_lines()
new_lines = statement_line.line_ids - (liquidity_line + other_lines + new_suspense_line)
statement_line._create_tax_lines(original_base_lines, original_tax_lines, new_lines)
if self.next_activity_type_id:
statement_line.move_id.activity_schedule(
activity_type_id=self.next_activity_type_id.id,
user_id=self.env.user.id,
)
def trigger_reconciliation_model(self, statement_line_id):
self.ensure_one()
statement_line = self.env['account.bank.statement.line'].browse(statement_line_id).exists()
self._trigger_reconciliation_model(statement_line)
def write(self, vals):
res = super().write(vals)
unreconciled_statement_lines = self.env['account.bank.statement.line'].search([
*self._check_company_domain(self.env.company),
('is_reconciled', '=', False),
])
if unreconciled_statement_lines:
unreconciled_statement_lines.line_ids.filtered(
lambda line:
line.account_id == line.move_id.journal_id.suspense_account_id and line.reconcile_model_id in self
).reconcile_model_id = False
self._apply_reconcile_models(unreconciled_statement_lines)
return res
@api.model_create_multi
def create(self, vals_list):
reco_models = super().create(vals_list)
unreconciled_statement_lines = self.env['account.bank.statement.line'].search([
*self._check_company_domain(self.env.company),
('is_reconciled', '=', False),
])
if unreconciled_statement_lines:
reco_models._apply_reconcile_models(unreconciled_statement_lines)
return reco_models
def action_archive(self):
res = super().action_archive()
unreconciled_statement_lines = self.env['account.bank.statement.line'].search([
*self._check_company_domain(self.env.company),
('is_reconciled', '=', False),
('line_ids.reconcile_model_id', 'in', self.ids),
])
if unreconciled_statement_lines:
unreconciled_statement_lines.line_ids.filtered(
lambda line:
line.account_id == line.move_id.journal_id.suspense_account_id
).reconcile_model_id = False
return res

View File

@@ -0,0 +1,139 @@
import { EventBus, reactive, useState } from "@odoo/owl";
import { browser } from "@web/core/browser/browser";
import { useService } from "@web/core/utils/hooks";
import { registry } from "@web/core/registry";
export class BankReconciliationService {
constructor(env, services) {
this.env = env;
this.setup(env, services);
}
setup(env, services) {
this.bus = new EventBus();
this.orm = services["orm"];
this.chatterState = reactive({
visible:
JSON.parse(
browser.sessionStorage.getItem("isBankReconciliationWidgetChatterOpened")
) ?? false,
statementLine: null,
});
this.reconcileCountPerPartnerId = reactive({});
this.reconcileModelPerStatementLineId = reactive({});
}
toggleChatter() {
this.chatterState.visible = !this.chatterState.visible;
browser.sessionStorage.setItem(
"isBankReconciliationWidgetChatterOpened",
this.chatterState.visible
);
}
/**
* Specific function to open the chatter.
* For a particular case, where the customer clicks on
* the chatter icon directly on the bank statement line,
* we want to open the chatter but not close it.
*/
openChatter() {
this.chatterState.visible = true;
}
selectStatementLine(statementLine) {
this.chatterState.statementLine = statementLine;
}
reloadChatter() {
this.bus.trigger("MAIL:RELOAD-THREAD", {
model: "account.move",
id: this.statementLineMoveId,
});
}
async computeReconcileLineCountPerPartnerId(records) {
const groups = await this.orm.formattedReadGroup(
"account.move.line",
[
["parent_state", "in", ["draft", "posted"]],
[
"partner_id",
"in",
records
.filter((record) => !!record.data.partner_id.id)
.map((record) => record.data.partner_id.id),
],
["company_id", "child_of", records.map((record) => record.data.company_id.id)],
["search_account_id.reconcile", "=", true],
["display_type", "not in", ["line_section", "line_note"]],
["reconciled", "=", false],
"|",
["search_account_id.account_type", "not in", ["asset_receivable", "liability_payable"]],
["payment_id", "=", false],
["statement_line_id", "not in", records.map((record) => record.data.id)],
],
["partner_id"],
["id:count"]
);
this.reconcileCountPerPartnerId = {};
groups.forEach((group) => {
this.reconcileCountPerPartnerId[group.partner_id[0]] = group["id:count"];
});
}
async computeAvailableReconcileModels(records) {
this.reconcileModelPerStatementLineId =
Object.keys(records).length === 0
? {}
: await this.orm.call(
"account.reconcile.model",
"get_available_reconcile_model_per_statement_line",
[records.map((record) => record.data.id)]
);
}
async updateAvailableReconcileModels(recordId) {
const result = await this.orm.call(
"account.reconcile.model",
"get_available_reconcile_model_per_statement_line",
[[recordId]]
);
this.reconcileModelPerStatementLineId[recordId] = result[recordId];
}
async reloadRecords(records) {
await Promise.all([...records.map((record) => record.load())]);
}
get statementLineMove() {
return this.chatterState.statementLine?.data.move_id;
}
get statementLineMoveId() {
return this.statementLineMove?.id;
}
get statementLine() {
return this.chatterState.statementLine;
}
get statementLineId() {
return this.statementLine?.data?.id;
}
}
const bankReconciliationService = {
dependencies: ["orm"],
start(env, services) {
return new BankReconciliationService(env, services);
},
};
registry.category("services").add("bankReconciliation", bankReconciliationService);
export function useBankReconciliation() {
return useState(useService("bankReconciliation"));
}

View File

@@ -0,0 +1,442 @@
# Graph Report - /Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec (2026-04-22)
## Corpus Check
- 85 files · ~29,014 words
- Verdict: corpus is large enough that graph structure adds value.
## Summary
- 792 nodes · 1381 edges · 66 communities detected
- Extraction: 65% EXTRACTED · 35% INFERRED · 0% AMBIGUOUS · INFERRED: 482 edges (avg confidence: 0.71)
- Token cost: 0 input · 0 output
## Community Hubs (Navigation)
- [[_COMMUNITY_Community 0|Community 0]]
- [[_COMMUNITY_Community 1|Community 1]]
- [[_COMMUNITY_Community 2|Community 2]]
- [[_COMMUNITY_Community 3|Community 3]]
- [[_COMMUNITY_Community 4|Community 4]]
- [[_COMMUNITY_Community 5|Community 5]]
- [[_COMMUNITY_Community 6|Community 6]]
- [[_COMMUNITY_Community 7|Community 7]]
- [[_COMMUNITY_Community 8|Community 8]]
- [[_COMMUNITY_Community 9|Community 9]]
- [[_COMMUNITY_Community 10|Community 10]]
- [[_COMMUNITY_Community 11|Community 11]]
- [[_COMMUNITY_Community 12|Community 12]]
- [[_COMMUNITY_Community 13|Community 13]]
- [[_COMMUNITY_Community 14|Community 14]]
- [[_COMMUNITY_Community 15|Community 15]]
- [[_COMMUNITY_Community 16|Community 16]]
- [[_COMMUNITY_Community 17|Community 17]]
- [[_COMMUNITY_Community 18|Community 18]]
- [[_COMMUNITY_Community 19|Community 19]]
- [[_COMMUNITY_Community 20|Community 20]]
- [[_COMMUNITY_Community 21|Community 21]]
- [[_COMMUNITY_Community 22|Community 22]]
- [[_COMMUNITY_Community 23|Community 23]]
- [[_COMMUNITY_Community 24|Community 24]]
- [[_COMMUNITY_Community 25|Community 25]]
- [[_COMMUNITY_Community 26|Community 26]]
- [[_COMMUNITY_Community 27|Community 27]]
- [[_COMMUNITY_Community 28|Community 28]]
- [[_COMMUNITY_Community 29|Community 29]]
- [[_COMMUNITY_Community 30|Community 30]]
- [[_COMMUNITY_Community 31|Community 31]]
- [[_COMMUNITY_Community 32|Community 32]]
- [[_COMMUNITY_Community 33|Community 33]]
- [[_COMMUNITY_Community 34|Community 34]]
- [[_COMMUNITY_Community 35|Community 35]]
- [[_COMMUNITY_Community 36|Community 36]]
- [[_COMMUNITY_Community 37|Community 37]]
- [[_COMMUNITY_Community 38|Community 38]]
- [[_COMMUNITY_Community 39|Community 39]]
- [[_COMMUNITY_Community 40|Community 40]]
- [[_COMMUNITY_Community 41|Community 41]]
- [[_COMMUNITY_Community 42|Community 42]]
- [[_COMMUNITY_Community 43|Community 43]]
- [[_COMMUNITY_Community 44|Community 44]]
- [[_COMMUNITY_Community 45|Community 45]]
- [[_COMMUNITY_Community 46|Community 46]]
- [[_COMMUNITY_Community 47|Community 47]]
- [[_COMMUNITY_Community 48|Community 48]]
- [[_COMMUNITY_Community 49|Community 49]]
- [[_COMMUNITY_Community 50|Community 50]]
- [[_COMMUNITY_Community 51|Community 51]]
- [[_COMMUNITY_Community 52|Community 52]]
- [[_COMMUNITY_Community 53|Community 53]]
- [[_COMMUNITY_Community 54|Community 54]]
- [[_COMMUNITY_Community 55|Community 55]]
- [[_COMMUNITY_Community 56|Community 56]]
- [[_COMMUNITY_Community 57|Community 57]]
- [[_COMMUNITY_Community 58|Community 58]]
- [[_COMMUNITY_Community 59|Community 59]]
- [[_COMMUNITY_Community 60|Community 60]]
- [[_COMMUNITY_Community 61|Community 61]]
- [[_COMMUNITY_Community 62|Community 62]]
- [[_COMMUNITY_Community 63|Community 63]]
- [[_COMMUNITY_Community 64|Community 64]]
- [[_COMMUNITY_Community 65|Community 65]]
## God Nodes (most connected - your core abstractions)
1. `create()` - 71 edges
2. `Candidate` - 54 edges
3. `make_bank_line()` - 41 edges
4. `MultiInvoiceStrategy` - 37 edges
5. `AmountExactStrategy` - 36 edges
6. `FIFOStrategy` - 35 edges
7. `BankRecStatementLine` - 33 edges
8. `BankReconciliationService` - 31 edges
9. `reconcile_one()` - 30 edges
10. `BankRecButtonList` - 29 edges
## Surprising Connections (you probably didn't know these)
- `reconcile_manual()` --calls--> `reconcile_one()` [INFERRED]
/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/controllers/bank_rec_controller.py → /Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_reconcile_engine.py
- `bulk_reconcile()` --calls--> `reconcile_batch()` [INFERRED]
/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/controllers/bank_rec_controller.py → /Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_reconcile_engine.py
- `4-pass confidence scoring pipeline. Pass 1: SQL filter — partner match + reconc` --uses--> `Candidate` [INFERRED]
/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/confidence_scoring.py → /Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/matching_strategies.py
- `Score and rank candidate matches for a statement line. Args: env: O` --uses--> `Candidate` [INFERRED]
/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/confidence_scoring.py → /Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/matching_strategies.py
- `How well does this candidate fit the partner's typical pattern?` --uses--> `Candidate` [INFERRED]
/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/confidence_scoring.py → /Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/matching_strategies.py
## Communities
### Community 0 - "Community 0"
Cohesion: 0.03
Nodes (52): create(), suggest_matches(), FusionBulkReconcileWizard, Bulk reconcile wizard — operates on user-selected records. Reads active_ids fro, _ensure_test_product(), make_bank_journal(), make_bank_line(), make_bank_statement() (+44 more)
### Community 1 - "Community 1"
Cohesion: 0.09
Nodes (42): FusionReconcileEngine, The reconcile engine — orchestrator for all bank-line reconciliations. Public A, Bulk-reconcile a recordset using the chosen strategy. Returns: ``{'reco, Compute and persist AI suggestions per line. Returns: dict mapping ``li, User clicked Accept on a suggestion -> reconcile via its proposal. Retu, Create a write-off move + reconcile the bank line against it. Returns:, Reverse a reconciliation. Handles full vs. partial chains. Because ``re, Phase 2: structural + safety checks. (+34 more)
### Community 2 - "Community 2"
Cohesion: 0.04
Nodes (3): BankRecButtonList, BankRecLineToReconcile, BankRecReconciledLineName
### Community 3 - "Community 3"
Cohesion: 0.04
Nodes (5): AiAlternativesPanel, AiSuggestionStrip, BankRecKanbanController, BankReconciliationService, BatchActionBar
### Community 4 - "Community 4"
Cohesion: 0.06
Nodes (25): _ai_rerank(), _build_reasoning(), _get_provider(), _pattern_score(), _precedent_score(), 4-pass confidence scoring pipeline. Pass 1: SQL filter — partner match + reconc, How similar is this candidate to past precedents?, Look up provider name from per-feature config; instantiate adapter. Returns (+17 more)
### Community 5 - "Community 5"
Cohesion: 0.08
Nodes (23): accept_suggestion(), _adapter(), bulk_reconcile(), FusionBankRecController, list_unreconciled(), HTTP controller: 10 JSON-RPC endpoints for the OWL bank-rec widget. All endpoin, Resolve the bank-rec data adapter from fusion_accounting_ai., JSON-RPC surface consumed by the OWL bank-reconciliation widget. All routes (+15 more)
### Community 6 - "Community 6"
Cohesion: 0.08
Nodes (22): make_reconcileable_pair(), Create a bank line + a customer invoice with the same partner+amount. Return, accept_suggestion(), reconcile_batch(), reconcile_one(), write_off(), Tests verifying legacy tools route through fusion.reconcile.engine when present., When engine is present, match_bank_line_to_payments must produce a parti (+14 more)
### Community 7 - "Community 7"
Cohesion: 0.06
Nodes (2): useBankReconciliation(), BankRecStatementLine
### Community 8 - "Community 8"
Cohesion: 0.11
Nodes (6): AccountReconcileModel, Apply the reconciliation model lines to the statement line passed as parameter., FusionAutoReconcileWizard, Auto-reconcile wizard. Lets the user pick filters (journal, date range, strateg, The fusion.reconcile.suggestion state machine + computed band., TestSuggestionLifecycle
### Community 9 - "Community 9"
Cohesion: 0.09
Nodes (13): Tests for BankRecAdapter's fusion paths., Smoke tests for the 5 new fusion bank-rec AI tools., Tests for fusion.bulk.reconcile.wizard., Tests for the fusion bank-rec HTTP controller (Task 26). Uses ``HttpCase`` so w, Smoke tests for the cron handler methods. We don't test the Odoo cron scheduler, Smoke tests verifying the factories produce usable records. Not testing factory, _detect_local_llm(), Local LLM compatibility test (LM Studio, Ollama, etc.). Skips if no local OpenA (+5 more)
### Community 10 - "Community 10"
Cohesion: 0.15
Nodes (9): _cron_refresh_mv(), FusionBankRecCron, Cron handler model for fusion_accounting_bank_rec. Three scheduled jobs: - _cro, _amounts_concentrated(), extract_pattern_for_partner(), Aggregate per-partner reconciliation patterns from precedent rows. Computes typ, Compute the pattern aggregate for one (company, partner) pair. Returns vals, True if amounts cluster around a few values (suggests exact-amount strategy). (+1 more)
### Community 11 - "Community 11"
Cohesion: 0.13
Nodes (9): create(), FusionReconcileSuggestion, Persisted AI suggestions for bank line reconciliations. One row per (statement_, Best-effort MV refresh; never poison the originating transaction. Uses, FusionUnreconciledBankLineMV, Materialized view exposing pre-aggregated unreconciled-bank-line data. The MV i, Create the MV if missing. Reads create_mv_unreconciled_bank_line.sql an, _refresh() (+1 more)
### Community 12 - "Community 12"
Cohesion: 0.12
Nodes (1): BankReconciliationService
### Community 13 - "Community 13"
Cohesion: 0.2
Nodes (9): AccountAutoReconcileWizard, default_get(), _get_default_wizard_values(), Auto-reconcile with one-to-one strategy: We will reconcile 2 amls togeth, Auto-reconcile with zero balance strategy: We will reconcile all amls gr, Automatically reconcile amls given wizard's parameters. :return: an acti, Get the current configuration of the wizard as a dict of values. :return, This wizard is used to automatically reconcile account.move.line. It is acce (+1 more)
### Community 14 - "Community 14"
Cohesion: 0.22
Nodes (8): compute_exchange_diff(), ExchangeDiffResult, Exchange-difference calculation helper. Pure-Python FX gain/loss computation. T, Compute whether an exchange-diff move is needed and its magnitude. Args:, USD invoice posted at 1.35, USD bank line settled at 1.40 -> diff exists., USD invoice at 1.40, settled at 1.35 -> loss, Tiny FX rounding under 0.005 should NOT trigger a diff move., TestExchangeDiff
### Community 15 - "Community 15"
Cohesion: 0.16
Nodes (6): Coexistence tests: fusion_accounting_bank_rec menus only visible when Enterprise, When account_accountant is installed, group should be empty., When account_accountant is uninstalled, all internal users get the group., The fusion bank-rec root menu must have the coexistence group attached., The reconcile engine must work even when Enterprise is installed (it's t, TestCoexistence
### Community 16 - "Community 16"
Cohesion: 0.17
Nodes (1): BankRecLineInfoPopOver
### Community 17 - "Community 17"
Cohesion: 0.22
Nodes (6): FusionMigrationWizard, Bank-rec specific migration step. Hooks into fusion.migration.wizard (defined b, Override the migration entry-point to add the bank-rec step. Calls supe, _identify_bank_side(), Pure-Python helpers for backfilling fusion.reconcile.precedent from existing acc, Return (bank_move_line, counterpart_move_line, statement_line_id) or (None,
### Community 18 - "Community 18"
Cohesion: 0.25
Nodes (2): Python wrappers that run the OWL tours via HttpCase.start_tour. Tours require a, TestBankRecTours
### Community 19 - "Community 19"
Cohesion: 0.25
Nodes (2): BankRecListController, BankRecListRenderer
### Community 20 - "Community 20"
Cohesion: 0.29
Nodes (1): BankRecSelectCreateDialog
### Community 21 - "Community 21"
Cohesion: 0.4
Nodes (2): BankRecEditLineFormController, BankRecFormDialog
### Community 22 - "Community 22"
Cohesion: 0.4
Nodes (1): BankRecWidgetApplyAmountHtmlField
### Community 23 - "Community 23"
Cohesion: 0.33
Nodes (2): BankRecReconcileDialogListController, BankRecReconcileDialogListRenderer
### Community 24 - "Community 24"
Cohesion: 0.4
Nodes (2): AccountBankStatementLine, Inherit account.bank.statement.line to add Phase 1 widget compute fields. These
### Community 25 - "Community 25"
Cohesion: 0.4
Nodes (3): FusionBankRecWidget, Per-request widget state. Holds the kanban-load response shape so the controller, Return a window action opening the OWL kanban for this journal.
### Community 26 - "Community 26"
Cohesion: 0.5
Nodes (1): ReconcileModelPicker
### Community 27 - "Community 27"
Cohesion: 0.5
Nodes (1): AttachmentStrip
### Community 28 - "Community 28"
Cohesion: 0.5
Nodes (1): BankRecFileUploader
### Community 29 - "Community 29"
Cohesion: 0.5
Nodes (2): BankRecQuickCreate, BankRecQuickCreateController
### Community 30 - "Community 30"
Cohesion: 0.5
Nodes (1): PartnerHistoryPanel
### Community 31 - "Community 31"
Cohesion: 0.5
Nodes (2): FusionMigrationAuditReport, QWeb PDF report: summary of bank-rec migration outcomes. Triggered from the mig
### Community 32 - "Community 32"
Cohesion: 0.67
Nodes (2): FusionReconcilePrecedent, Per-historical-decision reconciliation memory. One row per past reconciliation.
### Community 33 - "Community 33"
Cohesion: 0.67
Nodes (2): FusionReconcilePattern, Per-partner bank reconciliation pattern aggregate. One row per (company_id, par
### Community 34 - "Community 34"
Cohesion: 0.67
Nodes (2): AccountReconcileModel, Inherit account.reconcile.model to add Phase 1 AI integration hooks. This is a
### Community 35 - "Community 35"
Cohesion: 0.67
Nodes (1): AiReasoningTooltip
### Community 36 - "Community 36"
Cohesion: 0.67
Nodes (1): BankRecChatter
### Community 37 - "Community 37"
Cohesion: 0.67
Nodes (1): BankRecButton
### Community 38 - "Community 38"
Cohesion: 0.67
Nodes (1): BankRecStatementSummary
### Community 39 - "Community 39"
Cohesion: 0.67
Nodes (1): BankRecMany2OneMultiID
### Community 40 - "Community 40"
Cohesion: 1.0
Nodes (1): BankRecLineCard
### Community 41 - "Community 41"
Cohesion: 1.0
Nodes (0):
### Community 42 - "Community 42"
Cohesion: 1.0
Nodes (0):
### Community 43 - "Community 43"
Cohesion: 1.0
Nodes (0):
### Community 44 - "Community 44"
Cohesion: 1.0
Nodes (0):
### Community 45 - "Community 45"
Cohesion: 1.0
Nodes (0):
### Community 46 - "Community 46"
Cohesion: 1.0
Nodes (0):
### Community 47 - "Community 47"
Cohesion: 1.0
Nodes (0):
### Community 48 - "Community 48"
Cohesion: 1.0
Nodes (1): For each unreconciled bank line that doesn't have a recent pending sugge
### Community 49 - "Community 49"
Cohesion: 1.0
Nodes (1): For each (company, partner) pair with precedents, recompute and upsert t
### Community 50 - "Community 50"
Cohesion: 1.0
Nodes (1): Refresh the materialized view CONCURRENTLY using an autocommit cursor.
### Community 51 - "Community 51"
Cohesion: 1.0
Nodes (1): Refresh the MV. If ``concurrently=True`` (default), uses REFRES
### Community 52 - "Community 52"
Cohesion: 1.0
Nodes (1): Derive a preset configuration based on amls. For example if all amls hav
### Community 53 - "Community 53"
Cohesion: 1.0
Nodes (0):
### Community 54 - "Community 54"
Cohesion: 1.0
Nodes (0):
### Community 55 - "Community 55"
Cohesion: 1.0
Nodes (0):
### Community 56 - "Community 56"
Cohesion: 1.0
Nodes (1): Return the journal summary that seeds the kanban widget.
### Community 57 - "Community 57"
Cohesion: 1.0
Nodes (1): Return enriched, paginated unreconciled bank lines.
### Community 58 - "Community 58"
Cohesion: 1.0
Nodes (1): Return full detail for one line including pending suggestions.
### Community 59 - "Community 59"
Cohesion: 1.0
Nodes (1): Trigger AI suggest for one or more statement lines.
### Community 60 - "Community 60"
Cohesion: 1.0
Nodes (1): Accept a fusion suggestion. Returns the partial IDs created.
### Community 61 - "Community 61"
Cohesion: 1.0
Nodes (1): Reconcile a line against an explicit set of journal items.
### Community 62 - "Community 62"
Cohesion: 1.0
Nodes (1): Reverse one or more partial reconciles.
### Community 63 - "Community 63"
Cohesion: 1.0
Nodes (1): Apply a write-off against a bank statement line.
### Community 64 - "Community 64"
Cohesion: 1.0
Nodes (1): Batch auto-reconcile. Returns counts + per-line errors.
### Community 65 - "Community 65"
Cohesion: 1.0
Nodes (1): Return a partner's reconcile history + learned pattern.
## Knowledge Gaps
- **115 isolated node(s):** `Smoke tests for the fusion_unreconciled_bank_line_mv materialized view. Notes o`, `Tests for fusion.bulk.reconcile.wizard.`, `Local LLM compatibility test (LM Studio, Ollama, etc.). Skips if no local OpenA`, `Return (base_url, model_name) tuple, or (None, None) if no server. Tries LM`, `Smoke tests for the 5 new fusion bank-rec AI tools.` (+110 more)
These have ≤1 connection - possible missing edges or undocumented components.
- **Thin community `Community 40`** (2 nodes): `BankRecLineCard`, `bank_rec_kanban_renderer.js`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 41`** (1 nodes): `__init__.py`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 42`** (1 nodes): `__init__.py`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 43`** (1 nodes): `__init__.py`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 44`** (1 nodes): `__init__.py`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 45`** (1 nodes): `__init__.py`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 46`** (1 nodes): `__init__.py`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 47`** (1 nodes): `__manifest__.py`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 48`** (1 nodes): `For each unreconciled bank line that doesn't have a recent pending sugge`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 49`** (1 nodes): `For each (company, partner) pair with precedents, recompute and upsert t`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 50`** (1 nodes): `Refresh the materialized view CONCURRENTLY using an autocommit cursor.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 51`** (1 nodes): `Refresh the MV. If ``concurrently=True`` (default), uses REFRES`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 52`** (1 nodes): `Derive a preset configuration based on amls. For example if all amls hav`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 53`** (1 nodes): `bank_rec_tours.js`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 54`** (1 nodes): `bank_reconciliation_service.js`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 55`** (1 nodes): `bank_rec_kanban_view.js`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 56`** (1 nodes): `Return the journal summary that seeds the kanban widget.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 57`** (1 nodes): `Return enriched, paginated unreconciled bank lines.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 58`** (1 nodes): `Return full detail for one line including pending suggestions.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 59`** (1 nodes): `Trigger AI suggest for one or more statement lines.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 60`** (1 nodes): `Accept a fusion suggestion. Returns the partial IDs created.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 61`** (1 nodes): `Reconcile a line against an explicit set of journal items.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 62`** (1 nodes): `Reverse one or more partial reconciles.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 63`** (1 nodes): `Apply a write-off against a bank statement line.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 64`** (1 nodes): `Batch auto-reconcile. Returns counts + per-line errors.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 65`** (1 nodes): `Return a partner's reconcile history + learned pattern.`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
## Suggested Questions
_Questions this graph is uniquely positioned to answer:_
- **Why does `create()` connect `Community 0` to `Community 1`, `Community 4`, `Community 5`, `Community 6`, `Community 8`, `Community 10`, `Community 11`, `Community 18`?**
_High betweenness centrality (0.179) - this node is a cross-community bridge._
- **Why does `useBankReconciliation()` connect `Community 7` to `Community 2`?**
_High betweenness centrality (0.112) - this node is a cross-community bridge._
- **Are the 69 inferred relationships involving `create()` (e.g. with `.setUp()` and `.setUp()`) actually correct?**
_`create()` has 69 INFERRED edges - model-reasoned connections that need verification._
- **Are the 53 inferred relationships involving `Candidate` (e.g. with `TestConfidenceScoring` and `When no AI provider config, score_ai_rerank stays at 0.0.`) actually correct?**
_`Candidate` has 53 INFERRED edges - model-reasoned connections that need verification._
- **Are the 37 inferred relationships involving `make_bank_line()` (e.g. with `.test_mv_includes_unreconciled_line()` and `.test_mv_confidence_band_high_for_high_conf_suggestion()`) actually correct?**
_`make_bank_line()` has 37 INFERRED edges - model-reasoned connections that need verification._
- **Are the 33 inferred relationships involving `MultiInvoiceStrategy` (e.g. with `TestMatchingStrategyInvariants` and `TestReconcileEngineInvariants`) actually correct?**
_`MultiInvoiceStrategy` has 33 INFERRED edges - model-reasoned connections that need verification._
- **Are the 33 inferred relationships involving `AmountExactStrategy` (e.g. with `TestMatchingStrategyInvariants` and `TestReconcileEngineInvariants`) actually correct?**
_`AmountExactStrategy` has 33 INFERRED edges - model-reasoned connections that need verification._

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_controllers_init_py", "label": "__init__.py", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/controllers/__init__.py", "source_location": "L1"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_controllers_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_controllers_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/controllers/__init__.py", "source_location": "L1", "weight": 1.0}], "raw_calls": []}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_services_exchange_diff_py", "label": "exchange_diff.py", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/exchange_diff.py", "source_location": "L1"}, {"id": "exchange_diff_exchangediffresult", "label": "ExchangeDiffResult", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/exchange_diff.py", "source_location": "L12"}, {"id": "exchange_diff_compute_exchange_diff", "label": "compute_exchange_diff()", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/exchange_diff.py", "source_location": "L19"}, {"id": "exchange_diff_rationale_1", "label": "Exchange-difference calculation helper. Pure-Python FX gain/loss computation. T", "file_type": "rationale", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/exchange_diff.py", "source_location": "L1"}, {"id": "exchange_diff_rationale_21", "label": "Compute whether an exchange-diff move is needed and its magnitude. Args:", "file_type": "rationale", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/exchange_diff.py", "source_location": "L21"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_services_exchange_diff_py", "target": "dataclasses", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/exchange_diff.py", "source_location": "L8", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_services_exchange_diff_py", "target": "exchange_diff_exchangediffresult", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/exchange_diff.py", "source_location": "L12", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_services_exchange_diff_py", "target": "exchange_diff_compute_exchange_diff", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/exchange_diff.py", "source_location": "L19", "weight": 1.0}, {"source": "exchange_diff_compute_exchange_diff", "target": "exchange_diff_exchangediffresult", "relation": "calls", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/exchange_diff.py", "source_location": "L41", "weight": 1.0}, {"source": "exchange_diff_rationale_1", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_services_exchange_diff_py", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/exchange_diff.py", "source_location": "L1", "weight": 1.0}, {"source": "exchange_diff_rationale_21", "target": "exchange_diff_compute_exchange_diff", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/exchange_diff.py", "source_location": "L21", "weight": 1.0}], "raw_calls": [{"caller_nid": "exchange_diff_compute_exchange_diff", "callee": "abs", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/exchange_diff.py", "source_location": "L39"}, {"caller_nid": "exchange_diff_compute_exchange_diff", "callee": "round", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/exchange_diff.py", "source_location": "L43"}, {"caller_nid": "exchange_diff_compute_exchange_diff", "callee": "round", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/exchange_diff.py", "source_location": "L44"}, {"caller_nid": "exchange_diff_compute_exchange_diff", "callee": "round", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/exchange_diff.py", "source_location": "L45"}]}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_bank_reconciliation_service_js", "label": "bank_reconciliation_service.js", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/bank_reconciliation_service.js", "source_location": "L1"}], "edges": [], "raw_calls": []}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_ai_suggestion_ai_reasoning_tooltip_js", "label": "ai_reasoning_tooltip.js", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/ai_suggestion/ai_reasoning_tooltip.js", "source_location": "L1"}, {"id": "ai_reasoning_tooltip_aireasoningtooltip", "label": "AiReasoningTooltip", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/ai_suggestion/ai_reasoning_tooltip.js", "source_location": "L5"}, {"id": "ai_reasoning_tooltip_aireasoningtooltip_pctfor", "label": ".pctFor()", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/ai_suggestion/ai_reasoning_tooltip.js", "source_location": "L12"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_ai_suggestion_ai_reasoning_tooltip_js", "target": "owl", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/ai_suggestion/ai_reasoning_tooltip.js", "source_location": "L3", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_ai_suggestion_ai_reasoning_tooltip_js", "target": "ai_reasoning_tooltip_aireasoningtooltip", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/ai_suggestion/ai_reasoning_tooltip.js", "source_location": "L5", "weight": 1.0}, {"source": "ai_reasoning_tooltip_aireasoningtooltip", "target": "ai_reasoning_tooltip_aireasoningtooltip_pctfor", "relation": "method", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/ai_suggestion/ai_reasoning_tooltip.js", "source_location": "L12", "weight": 1.0}], "raw_calls": [{"caller_nid": "ai_reasoning_tooltip_aireasoningtooltip_pctfor", "callee": "toFixed", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/ai_suggestion/ai_reasoning_tooltip.js", "source_location": "L16"}]}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_statement_summary_statement_summary_js", "label": "statement_summary.js", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/statement_summary/statement_summary.js", "source_location": "L1"}, {"id": "statement_summary_bankrecstatementsummary", "label": "BankRecStatementSummary", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/statement_summary/statement_summary.js", "source_location": "L11"}, {"id": "statement_summary_bankrecstatementsummary_actionapplyinvalidstatement", "label": ".actionApplyInvalidStatement()", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/statement_summary/statement_summary.js", "source_location": "L26"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_statement_summary_statement_summary_js", "target": "owl", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/statement_summary/statement_summary.js", "source_location": "L9", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_statement_summary_statement_summary_js", "target": "statement_summary_bankrecstatementsummary", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/statement_summary/statement_summary.js", "source_location": "L11", "weight": 1.0}, {"source": "statement_summary_bankrecstatementsummary", "target": "statement_summary_bankrecstatementsummary_actionapplyinvalidstatement", "relation": "method", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/statement_summary/statement_summary.js", "source_location": "L26", "weight": 1.0}], "raw_calls": [{"caller_nid": "statement_summary_bankrecstatementsummary_actionapplyinvalidstatement", "callee": "find", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/statement_summary/statement_summary.js", "source_location": "L29"}, {"caller_nid": "statement_summary_bankrecstatementsummary_actionapplyinvalidstatement", "callee": "values", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/statement_summary/statement_summary.js", "source_location": "L29"}, {"caller_nid": "statement_summary_bankrecstatementsummary_actionapplyinvalidstatement", "callee": "filter", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/statement_summary/statement_summary.js", "source_location": "L32"}, {"caller_nid": "statement_summary_bankrecstatementsummary_actionapplyinvalidstatement", "callee": "includes", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/statement_summary/statement_summary.js", "source_location": "L37"}, {"caller_nid": "statement_summary_bankrecstatementsummary_actionapplyinvalidstatement", "callee": "toggleSearchItem", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/statement_summary/statement_summary.js", "source_location": "L39"}]}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_quick_create_quick_create_js", "label": "quick_create.js", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/quick_create/quick_create.js", "source_location": "L1"}, {"id": "quick_create_bankrecquickcreatecontroller", "label": "BankRecQuickCreateController", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/quick_create/quick_create.js", "source_location": "L13"}, {"id": "quick_create_bankrecquickcreate", "label": "BankRecQuickCreate", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/quick_create/quick_create.js", "source_location": "L17"}, {"id": "quick_create_bankrecquickcreate_getquickcreateprops", "label": ".getQuickCreateProps()", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/quick_create/quick_create.js", "source_location": "L32"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_quick_create_quick_create_js", "target": "kanban_record_quick_create", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/quick_create/quick_create.js", "source_location": "L8", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_quick_create_quick_create_js", "target": "quick_create_bankrecquickcreatecontroller", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/quick_create/quick_create.js", "source_location": "L13", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_quick_create_quick_create_js", "target": "quick_create_bankrecquickcreate", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/quick_create/quick_create.js", "source_location": "L17", "weight": 1.0}, {"source": "quick_create_bankrecquickcreate", "target": "quick_create_bankrecquickcreate_getquickcreateprops", "relation": "method", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/quick_create/quick_create.js", "source_location": "L32", "weight": 1.0}], "raw_calls": []}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_button_button_js", "label": "button.js", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/button/button.js", "source_location": "L1"}, {"id": "button_bankrecbutton", "label": "BankRecButton", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/button/button.js", "source_location": "L11"}, {"id": "button_bankrecbutton_setup", "label": ".setup()", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/button/button.js", "source_location": "L26"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_button_button_js", "target": "owl", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/button/button.js", "source_location": "L8", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_button_button_js", "target": "hooks", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/button/button.js", "source_location": "L9", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_button_button_js", "target": "button_bankrecbutton", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/button/button.js", "source_location": "L11", "weight": 1.0}, {"source": "button_bankrecbutton", "target": "button_bankrecbutton_setup", "relation": "method", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/button/button.js", "source_location": "L26", "weight": 1.0}], "raw_calls": [{"caller_nid": "button_bankrecbutton_setup", "callee": "useService", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/button/button.js", "source_location": "L27"}]}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_reports_init_py", "label": "__init__.py", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/reports/__init__.py", "source_location": "L1"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_reports_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_reports_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/reports/__init__.py", "source_location": "L1", "weight": 1.0}], "raw_calls": []}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_init_py", "label": "__init__.py", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/__init__.py", "source_location": "L1"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/__init__.py", "source_location": "L1", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/__init__.py", "source_location": "L2", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/__init__.py", "source_location": "L3", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/__init__.py", "source_location": "L4", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/__init__.py", "source_location": "L5", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/__init__.py", "source_location": "L6", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/__init__.py", "source_location": "L7", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/__init__.py", "source_location": "L8", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/__init__.py", "source_location": "L9", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/__init__.py", "source_location": "L10", "weight": 1.0}], "raw_calls": []}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_account_bank_statement_line_py", "label": "account_bank_statement_line.py", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/account_bank_statement_line.py", "source_location": "L1"}, {"id": "account_bank_statement_line_accountbankstatementline", "label": "AccountBankStatementLine", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/account_bank_statement_line.py", "source_location": "L12"}, {"id": "account_bank_statement_line_accountbankstatementline_compute_top_suggestion", "label": "._compute_top_suggestion()", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/account_bank_statement_line.py", "source_location": "L36"}, {"id": "account_bank_statement_line_compute_bank_statement_attachment_ids", "label": "_compute_bank_statement_attachment_ids()", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/account_bank_statement_line.py", "source_location": "L48"}, {"id": "account_bank_statement_line_rationale_1", "label": "Inherit account.bank.statement.line to add Phase 1 widget compute fields. These", "file_type": "rationale", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/account_bank_statement_line.py", "source_location": "L1"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_account_bank_statement_line_py", "target": "odoo", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/account_bank_statement_line.py", "source_location": "L9", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_account_bank_statement_line_py", "target": "account_bank_statement_line_accountbankstatementline", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/account_bank_statement_line.py", "source_location": "L12", "weight": 1.0}, {"source": "account_bank_statement_line_accountbankstatementline", "target": "account_bank_statement_line_accountbankstatementline_compute_top_suggestion", "relation": "method", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/account_bank_statement_line.py", "source_location": "L36", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_account_bank_statement_line_py", "target": "account_bank_statement_line_compute_bank_statement_attachment_ids", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/account_bank_statement_line.py", "source_location": "L48", "weight": 1.0}, {"source": "account_bank_statement_line_rationale_1", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_account_bank_statement_line_py", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/account_bank_statement_line.py", "source_location": "L1", "weight": 1.0}], "raw_calls": [{"caller_nid": "account_bank_statement_line_accountbankstatementline_compute_top_suggestion", "callee": "sudo", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/account_bank_statement_line.py", "source_location": "L37"}, {"caller_nid": "account_bank_statement_line_accountbankstatementline_compute_top_suggestion", "callee": "search", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/account_bank_statement_line.py", "source_location": "L39"}]}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_services_init_py", "label": "__init__.py", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/__init__.py", "source_location": "L1"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_services_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_services_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/__init__.py", "source_location": "L1", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_services_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_services_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/__init__.py", "source_location": "L2", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_services_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_services_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/__init__.py", "source_location": "L3", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_services_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_services_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/__init__.py", "source_location": "L4", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_services_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_services_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/__init__.py", "source_location": "L5", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_services_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_services_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/__init__.py", "source_location": "L6", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_services_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_services_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/services/__init__.py", "source_location": "L7", "weight": 1.0}], "raw_calls": []}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_file_uploader_file_uploader_js", "label": "file_uploader.js", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/file_uploader/file_uploader.js", "source_location": "L1"}, {"id": "file_uploader_bankrecfileuploader", "label": "BankRecFileUploader", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/file_uploader/file_uploader.js", "source_location": "L11"}, {"id": "file_uploader_bankrecfileuploader_getextracontext", "label": ".getExtraContext()", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/file_uploader/file_uploader.js", "source_location": "L18"}, {"id": "file_uploader_bankrecfileuploader_getresmodel", "label": ".getResModel()", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/file_uploader/file_uploader.js", "source_location": "L26"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_file_uploader_file_uploader_js", "target": "document_file_uploader", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/file_uploader/file_uploader.js", "source_location": "L9", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_file_uploader_file_uploader_js", "target": "file_uploader_bankrecfileuploader", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/file_uploader/file_uploader.js", "source_location": "L11", "weight": 1.0}, {"source": "file_uploader_bankrecfileuploader", "target": "file_uploader_bankrecfileuploader_getextracontext", "relation": "method", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/file_uploader/file_uploader.js", "source_location": "L18", "weight": 1.0}, {"source": "file_uploader_bankrecfileuploader", "target": "file_uploader_bankrecfileuploader_getresmodel", "relation": "method", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/file_uploader/file_uploader.js", "source_location": "L26", "weight": 1.0}], "raw_calls": []}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_attachment_strip_attachment_strip_js", "label": "attachment_strip.js", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/attachment_strip/attachment_strip.js", "source_location": "L1"}, {"id": "attachment_strip_attachmentstrip", "label": "AttachmentStrip", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/attachment_strip/attachment_strip.js", "source_location": "L5"}, {"id": "attachment_strip_attachmentstrip_iconfor", "label": ".iconFor()", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/attachment_strip/attachment_strip.js", "source_location": "L11"}, {"id": "attachment_strip_attachmentstrip_urlfor", "label": ".urlFor()", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/attachment_strip/attachment_strip.js", "source_location": "L24"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_attachment_strip_attachment_strip_js", "target": "owl", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/attachment_strip/attachment_strip.js", "source_location": "L3", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_attachment_strip_attachment_strip_js", "target": "attachment_strip_attachmentstrip", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/attachment_strip/attachment_strip.js", "source_location": "L5", "weight": 1.0}, {"source": "attachment_strip_attachmentstrip", "target": "attachment_strip_attachmentstrip_iconfor", "relation": "method", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/attachment_strip/attachment_strip.js", "source_location": "L11", "weight": 1.0}, {"source": "attachment_strip_attachmentstrip", "target": "attachment_strip_attachmentstrip_urlfor", "relation": "method", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/attachment_strip/attachment_strip.js", "source_location": "L24", "weight": 1.0}], "raw_calls": [{"caller_nid": "attachment_strip_attachmentstrip_iconfor", "callee": "startsWith", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/attachment_strip/attachment_strip.js", "source_location": "L15"}]}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_list_view_list_view_many2one_multi_edit_js", "label": "list_view_many2one_multi_edit.js", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/list_view/list_view_many2one_multi_edit.js", "source_location": "L1"}, {"id": "list_view_many2one_multi_edit_bankrecmany2onemultiid", "label": "BankRecMany2OneMultiID", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/list_view/list_view_many2one_multi_edit.js", "source_location": "L14"}, {"id": "list_view_many2one_multi_edit_bankrecmany2onemultiid_m2oprops", "label": ".m2oProps()", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/list_view/list_view_many2one_multi_edit.js", "source_location": "L19"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_list_view_list_view_many2one_multi_edit_js", "target": "owl", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/list_view/list_view_many2one_multi_edit.js", "source_location": "L9", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_list_view_list_view_many2one_multi_edit_js", "target": "registry", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/list_view/list_view_many2one_multi_edit.js", "source_location": "L10", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_list_view_list_view_many2one_multi_edit_js", "target": "many2one", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/list_view/list_view_many2one_multi_edit.js", "source_location": "L11", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_list_view_list_view_many2one_multi_edit_js", "target": "many2one_field", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/list_view/list_view_many2one_multi_edit.js", "source_location": "L12", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_list_view_list_view_many2one_multi_edit_js", "target": "list_view_many2one_multi_edit_bankrecmany2onemultiid", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/list_view/list_view_many2one_multi_edit.js", "source_location": "L14", "weight": 1.0}, {"source": "list_view_many2one_multi_edit_bankrecmany2onemultiid", "target": "list_view_many2one_multi_edit_bankrecmany2onemultiid_m2oprops", "relation": "method", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/list_view/list_view_many2one_multi_edit.js", "source_location": "L19", "weight": 1.0}], "raw_calls": [{"caller_nid": "list_view_many2one_multi_edit_bankrecmany2onemultiid_m2oprops", "callee": "computeM2OProps", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/list_view/list_view_many2one_multi_edit.js", "source_location": "L20"}, {"caller_nid": "list_view_many2one_multi_edit_bankrecmany2onemultiid_m2oprops", "callee": "map", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/list_view/list_view_many2one_multi_edit.js", "source_location": "L22"}]}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_manifest_py", "label": "__manifest__.py", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/__manifest__.py", "source_location": "L1"}], "edges": [], "raw_calls": []}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_views_kanban_bank_rec_kanban_renderer_js", "label": "bank_rec_kanban_renderer.js", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_renderer.js", "source_location": "L1"}, {"id": "bank_rec_kanban_renderer_bankreclinecard", "label": "BankRecLineCard", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_renderer.js", "source_location": "L12"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_views_kanban_bank_rec_kanban_renderer_js", "target": "owl", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_renderer.js", "source_location": "L10", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_views_kanban_bank_rec_kanban_renderer_js", "target": "bank_rec_kanban_renderer_bankreclinecard", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_renderer.js", "source_location": "L12", "weight": 1.0}], "raw_calls": []}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_fusion_bank_rec_widget_py", "label": "fusion_bank_rec_widget.py", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_bank_rec_widget.py", "source_location": "L1"}, {"id": "fusion_bank_rec_widget_fusionbankrecwidget", "label": "FusionBankRecWidget", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_bank_rec_widget.py", "source_location": "L12"}, {"id": "fusion_bank_rec_widget_fusionbankrecwidget_action_open_kanban", "label": ".action_open_kanban()", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_bank_rec_widget.py", "source_location": "L26"}, {"id": "fusion_bank_rec_widget_rationale_1", "label": "Per-request widget state. Holds the kanban-load response shape so the controller", "file_type": "rationale", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_bank_rec_widget.py", "source_location": "L1"}, {"id": "fusion_bank_rec_widget_rationale_27", "label": "Return a window action opening the OWL kanban for this journal.", "file_type": "rationale", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_bank_rec_widget.py", "source_location": "L27"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_fusion_bank_rec_widget_py", "target": "odoo", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_bank_rec_widget.py", "source_location": "L9", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_fusion_bank_rec_widget_py", "target": "fusion_bank_rec_widget_fusionbankrecwidget", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_bank_rec_widget.py", "source_location": "L12", "weight": 1.0}, {"source": "fusion_bank_rec_widget_fusionbankrecwidget", "target": "fusion_bank_rec_widget_fusionbankrecwidget_action_open_kanban", "relation": "method", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_bank_rec_widget.py", "source_location": "L26", "weight": 1.0}, {"source": "fusion_bank_rec_widget_rationale_1", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_fusion_bank_rec_widget_py", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_bank_rec_widget.py", "source_location": "L1", "weight": 1.0}, {"source": "fusion_bank_rec_widget_rationale_27", "target": "fusion_bank_rec_widget_fusionbankrecwidget_action_open_kanban", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_bank_rec_widget.py", "source_location": "L27", "weight": 1.0}], "raw_calls": [{"caller_nid": "fusion_bank_rec_widget_fusionbankrecwidget_action_open_kanban", "callee": "ensure_one", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_bank_rec_widget.py", "source_location": "L28"}]}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_tours_bank_rec_tours_js", "label": "bank_rec_tours.js", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/tours/bank_rec_tours.js", "source_location": "L1"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_tours_bank_rec_tours_js", "target": "registry", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/tours/bank_rec_tours.js", "source_location": "L3", "weight": 1.0}], "raw_calls": []}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_fusion_reconcile_precedent_py", "label": "fusion_reconcile_precedent.py", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_reconcile_precedent.py", "source_location": "L1"}, {"id": "fusion_reconcile_precedent_fusionreconcileprecedent", "label": "FusionReconcilePrecedent", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_reconcile_precedent.py", "source_location": "L11"}, {"id": "fusion_reconcile_precedent_rationale_1", "label": "Per-historical-decision reconciliation memory. One row per past reconciliation.", "file_type": "rationale", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_reconcile_precedent.py", "source_location": "L1"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_fusion_reconcile_precedent_py", "target": "odoo", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_reconcile_precedent.py", "source_location": "L8", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_fusion_reconcile_precedent_py", "target": "fusion_reconcile_precedent_fusionreconcileprecedent", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_reconcile_precedent.py", "source_location": "L11", "weight": 1.0}, {"source": "fusion_reconcile_precedent_rationale_1", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_fusion_reconcile_precedent_py", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_reconcile_precedent.py", "source_location": "L1", "weight": 1.0}], "raw_calls": []}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_wizards_init_py", "label": "__init__.py", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/wizards/__init__.py", "source_location": "L1"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_wizards_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_wizards_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/wizards/__init__.py", "source_location": "L1", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_wizards_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_wizards_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/wizards/__init__.py", "source_location": "L2", "weight": 1.0}], "raw_calls": []}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_init_py", "label": "__init__.py", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/__init__.py", "source_location": "L1"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/__init__.py", "source_location": "L1", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/__init__.py", "source_location": "L2", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/__init__.py", "source_location": "L3", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/__init__.py", "source_location": "L4", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_init_py", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_init_py", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/__init__.py", "source_location": "L5", "weight": 1.0}], "raw_calls": []}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_fusion_reconcile_pattern_py", "label": "fusion_reconcile_pattern.py", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_reconcile_pattern.py", "source_location": "L1"}, {"id": "fusion_reconcile_pattern_fusionreconcilepattern", "label": "FusionReconcilePattern", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_reconcile_pattern.py", "source_location": "L11"}, {"id": "fusion_reconcile_pattern_rationale_1", "label": "Per-partner bank reconciliation pattern aggregate. One row per (company_id, par", "file_type": "rationale", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_reconcile_pattern.py", "source_location": "L1"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_fusion_reconcile_pattern_py", "target": "odoo", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_reconcile_pattern.py", "source_location": "L8", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_fusion_reconcile_pattern_py", "target": "fusion_reconcile_pattern_fusionreconcilepattern", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_reconcile_pattern.py", "source_location": "L11", "weight": 1.0}, {"source": "fusion_reconcile_pattern_rationale_1", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_fusion_reconcile_pattern_py", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/fusion_reconcile_pattern.py", "source_location": "L1", "weight": 1.0}], "raw_calls": []}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_account_reconcile_model_py", "label": "account_reconcile_model.py", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/account_reconcile_model.py", "source_location": "L1"}, {"id": "account_reconcile_model_accountreconcilemodel", "label": "AccountReconcileModel", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/account_reconcile_model.py", "source_location": "L13"}, {"id": "account_reconcile_model_rationale_1", "label": "Inherit account.reconcile.model to add Phase 1 AI integration hooks. This is a", "file_type": "rationale", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/account_reconcile_model.py", "source_location": "L1"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_account_reconcile_model_py", "target": "odoo", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/account_reconcile_model.py", "source_location": "L10", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_account_reconcile_model_py", "target": "account_reconcile_model_accountreconcilemodel", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/account_reconcile_model.py", "source_location": "L13", "weight": 1.0}, {"source": "account_reconcile_model_rationale_1", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_models_account_reconcile_model_py", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/models/account_reconcile_model.py", "source_location": "L1", "weight": 1.0}], "raw_calls": []}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_reports_migration_audit_report_py", "label": "migration_audit_report.py", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/reports/migration_audit_report.py", "source_location": "L1"}, {"id": "migration_audit_report_fusionmigrationauditreport", "label": "FusionMigrationAuditReport", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/reports/migration_audit_report.py", "source_location": "L16"}, {"id": "migration_audit_report_get_report_values", "label": "_get_report_values()", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/reports/migration_audit_report.py", "source_location": "L21"}, {"id": "migration_audit_report_rationale_1", "label": "QWeb PDF report: summary of bank-rec migration outcomes. Triggered from the mig", "file_type": "rationale", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/reports/migration_audit_report.py", "source_location": "L1"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_reports_migration_audit_report_py", "target": "odoo", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/reports/migration_audit_report.py", "source_location": "L13", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_reports_migration_audit_report_py", "target": "migration_audit_report_fusionmigrationauditreport", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/reports/migration_audit_report.py", "source_location": "L16", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_reports_migration_audit_report_py", "target": "migration_audit_report_get_report_values", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/reports/migration_audit_report.py", "source_location": "L21", "weight": 1.0}, {"source": "migration_audit_report_rationale_1", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_reports_migration_audit_report_py", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/reports/migration_audit_report.py", "source_location": "L1", "weight": 1.0}], "raw_calls": [{"caller_nid": "migration_audit_report_get_report_values", "callee": "browse", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/reports/migration_audit_report.py", "source_location": "L23"}, {"caller_nid": "migration_audit_report_get_report_values", "callee": "search", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/reports/migration_audit_report.py", "source_location": "L30"}, {"caller_nid": "migration_audit_report_get_report_values", "callee": "append", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/reports/migration_audit_report.py", "source_location": "L31"}, {"caller_nid": "migration_audit_report_get_report_values", "callee": "search_count", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/reports/migration_audit_report.py", "source_location": "L33"}, {"caller_nid": "migration_audit_report_get_report_values", "callee": "search_count", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/reports/migration_audit_report.py", "source_location": "L37"}, {"caller_nid": "migration_audit_report_get_report_values", "callee": "search_count", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/reports/migration_audit_report.py", "source_location": "L40"}]}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_chatter_chatter_js", "label": "chatter.js", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/chatter/chatter.js", "source_location": "L1"}, {"id": "chatter_bankrecchatter", "label": "BankRecChatter", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/chatter/chatter.js", "source_location": "L10"}, {"id": "chatter_bankrecchatter_reloadparentview", "label": ".reloadParentView()", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/chatter/chatter.js", "source_location": "L13"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_chatter_chatter_js", "target": "chatter", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/chatter/chatter.js", "source_location": "L8", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_chatter_chatter_js", "target": "chatter_bankrecchatter", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/chatter/chatter.js", "source_location": "L10", "weight": 1.0}, {"source": "chatter_bankrecchatter", "target": "chatter_bankrecchatter_reloadparentview", "relation": "method", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/chatter/chatter.js", "source_location": "L13", "weight": 1.0}], "raw_calls": [{"caller_nid": "chatter_bankrecchatter_reloadparentview", "callee": "load", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/chatter/chatter.js", "source_location": "L14"}]}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_views_kanban_bank_rec_kanban_view_js", "label": "bank_rec_kanban_view.js", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_view.js", "source_location": "L1"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_views_kanban_bank_rec_kanban_view_js", "target": "registry", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_view.js", "source_location": "L9", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_views_kanban_bank_rec_kanban_view_js", "target": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_views_kanban_bank_rec_kanban_controller", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_view.js", "source_location": "L10", "weight": 1.0}], "raw_calls": []}

View File

@@ -0,0 +1 @@
{"nodes": [{"id": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_partner_history_panel_partner_history_panel_js", "label": "partner_history_panel.js", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/partner_history_panel/partner_history_panel.js", "source_location": "L1"}, {"id": "partner_history_panel_partnerhistorypanel", "label": "PartnerHistoryPanel", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/partner_history_panel/partner_history_panel.js", "source_location": "L6"}, {"id": "partner_history_panel_partnerhistorypanel_setup", "label": ".setup()", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/partner_history_panel/partner_history_panel.js", "source_location": "L12"}, {"id": "partner_history_panel_partnerhistorypanel_formatamount", "label": ".formatAmount()", "file_type": "code", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/partner_history_panel/partner_history_panel.js", "source_location": "L28"}], "edges": [{"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_partner_history_panel_partner_history_panel_js", "target": "owl", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/partner_history_panel/partner_history_panel.js", "source_location": "L3", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_partner_history_panel_partner_history_panel_js", "target": "hooks", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/partner_history_panel/partner_history_panel.js", "source_location": "L4", "weight": 1.0}, {"source": "users_gurpreet_github_odoo_modules_fusion_accounting_bank_rec_static_src_components_bank_reconciliation_partner_history_panel_partner_history_panel_js", "target": "partner_history_panel_partnerhistorypanel", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/partner_history_panel/partner_history_panel.js", "source_location": "L6", "weight": 1.0}, {"source": "partner_history_panel_partnerhistorypanel", "target": "partner_history_panel_partnerhistorypanel_setup", "relation": "method", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/partner_history_panel/partner_history_panel.js", "source_location": "L12", "weight": 1.0}, {"source": "partner_history_panel_partnerhistorypanel", "target": "partner_history_panel_partnerhistorypanel_formatamount", "relation": "method", "confidence": "EXTRACTED", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/partner_history_panel/partner_history_panel.js", "source_location": "L28", "weight": 1.0}], "raw_calls": [{"caller_nid": "partner_history_panel_partnerhistorypanel_setup", "callee": "useService", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/partner_history_panel/partner_history_panel.js", "source_location": "L13"}, {"caller_nid": "partner_history_panel_partnerhistorypanel_setup", "callee": "useState", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/partner_history_panel/partner_history_panel.js", "source_location": "L14"}, {"caller_nid": "partner_history_panel_partnerhistorypanel_setup", "callee": "onWillStart", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/partner_history_panel/partner_history_panel.js", "source_location": "L16"}, {"caller_nid": "partner_history_panel_partnerhistorypanel_formatamount", "callee": "toFixed", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/partner_history_panel/partner_history_panel.js", "source_location": "L32"}, {"caller_nid": "partner_history_panel_partnerhistorypanel_formatamount", "callee": "Number", "source_file": "/Users/gurpreet/Github/Odoo-Modules/fusion_accounting_bank_rec/static/src/components/bank_reconciliation/partner_history_panel/partner_history_panel.js", "source_location": "L32"}]}

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More