Skip to content

[18.0][ADD] splitstudio lead import - #4

Merged
marcelsavegnago merged 3 commits into
18.0from
18.0-add-splitstudio_lead_import
Sep 11, 2026
Merged

[18.0][ADD] splitstudio lead import#4
marcelsavegnago merged 3 commits into
18.0from
18.0-add-splitstudio_lead_import

Conversation

@parzewski

Copy link
Copy Markdown
Contributor

Summary

Adds a new splitstudio_lead_import module to split-addons: a persistent
wizard that imports CRM leads from XLSX/CSV spreadsheets with advanced
duplicate detection and rich header-to-field mapping.

The wizard is models.Model (not models.TransientModel) so import
sessions can be saved, listed and reviewed later from the new Import
Sessions
menu.

Features

  • Duplicate detection before any record is created, against both
    crm.lead and res.partner (email, lead/contact name, company name).
  • Auto-creation of missing utm.campaign and crm.tag records from
    the spreadsheet (mirrors how tags were already handled).
  • Country resolution by ISO code first (BR, US), then by name
    (Brazil, United States).
  • Description column is stored on the lead and posted as a
    chatter internal note (mail.mt_note, visible in Anotações
    internas
    ).
  • Priority column maps English (Low/Medium/High/Very High),
    Portuguese (Baixa/Média/Alta/Muito Alta) and numeric
    (0/1/2/3) values to the crm.lead priority stars widget.
  • Recognised spreadsheet columns (English and Portuguese aliases):
    • oportunidade / opportunity / name (lead/opportunity name)
    • contact_name / Contato (person name for partner match)
    • email / email_from (email)
    • partner_name / Empresa (company name)
    • phone / Telefone
    • campaign / campaign_id / Campanha (auto-created if missing)
    • tags / tag_ids / Etiquetas (comma- or semicolon-separated,
      auto-created if missing)
    • description / Anotações internas (chatter internal note)
    • priority / Prioridade
    • website / Site
    • city / Cidade
    • country_id / País (ISO code or full name)
  • Pipelines menu replaces the default Leads menu and exposes
    one entry per sales team that has use_leads=True, so each pipeline
    has its own filtered action.
  • Move to another pipeline wizard (crm.lead.reassign.wizard)
    opens from the lead form header since team_id is now readonly
    to enforce pipeline discipline.

Tests

Adds tests/test_lead_import_fields.py with 9 tests covering the
header aliases, priority mapping (text and number), description +
chatter note, country resolution, website/city/country round-trip,
campaign auto-creation and duplicate detection. The existing
tests/test_lead_import_wizard.py was updated to provide a sales
team to the wizard (now required).

odoo.tests.result: 0 failed, 0 error(s) of 10 tests

Changelog

  • [ADD] initial commit (commit 8b6e2f8).
  • [LINT] apply pre-commit (ruff, ruff-format, pylint-odoo,
    oca-checks-odoo-module, oca-gen-addon-readme, whool-init,
    oca-gen-external-dependencies) (commit db80980).

Notes for reviewers

  • team_id is now readonly=True on the lead/opportunity form. Use
    the Move to another pipeline button in the form header to
    reassign a record to a different team.
  • The conversion wizard is overridden to restrict team_id to teams
    with use_opportunities=True (so a lead on the INTAKE team
    cannot be converted to an opportunity on SCOUT EVENTOS).
  • The wizard dropdown for team_id uses domain=[('use_leads', '=', True)] so you can only import into a pipeline that accepts
    leads.
  • A tools/link_orphans.py helper is shipped for one-off
    back-fills (linking orphan opportunities to a partner by name);
    it is not loaded by the manifest and is meant to be piped
    into odoo shell.

@parzewski parzewski changed the title 18.0 add splitstudio lead import [18.0][ADD][WIP] splitstudio lead import Sep 8, 2026
@parzewski parzewski self-assigned this Sep 8, 2026
@parzewski
parzewski force-pushed the 18.0-add-splitstudio_lead_import branch 2 times, most recently from 1cd8d5b to 513cc75 Compare September 8, 2026 22:47
@codecov

codecov Bot commented Sep 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (3aa1649) to head (6e16d62).

Additional details and impacted files
@@             Coverage Diff             @@
##              18.0        #4     +/-   ##
===========================================
  Coverage   100.00%   100.00%             
===========================================
  Files            2        17     +15     
  Lines           45      1427   +1382     
  Branches         0       108    +108     
===========================================
+ Hits            45      1427   +1382     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

parzewski added a commit that referenced this pull request Sep 8, 2026
Codecov flagged the lead_reassign_wizard module as 0% covered on
PR #4 (16 of 16 new lines missed). Add a dedicated test file
that exercises every public path:

  - _onchange_lead_id: lead, opportunity and empty-lead branches
  - action_reassign: happy path (lead moves to new team) and the
    same-team no-op early return
  - action_open_reassign_wizard: server-action entry point from
    the lead/opportunity header, for both lead and opportunity
    contexts (default_lead_id, default_new_team_id, and
    default_domain_new_team_id are all asserted)

The test class sets up isolated crm.team records and a lead and
an opportunity in setUpClass so it can run as a standard
TransactionCase without polluting the demo data.

Importing the new module from tests/__init__.py registers the
test class with the Odoo test runner.
parzewski added a commit that referenced this pull request Sep 8, 2026
Codecov flagged the lead_reassign_wizard module as 0% covered on
PR #4 (16 of 16 new lines missed). Add a dedicated test file
that exercises every public path:

  - _onchange_lead_id: lead, opportunity and empty-lead branches
  - action_reassign: happy path (lead moves to new team) and the
    same-team no-op early return
  - action_open_reassign_wizard: server-action entry point from
    the lead/opportunity header, for both lead and opportunity
    contexts (default_lead_id, default_new_team_id, and
    default_domain_new_team_id are all asserted)

The test class sets up isolated crm.team records and a lead and
an opportunity in setUpClass so it can run as a standard
TransactionCase without polluting the demo data.

Importing the new module from tests/__init__.py registers the
test class with the Odoo test runner.
@parzewski
parzewski force-pushed the 18.0-add-splitstudio_lead_import branch from 2b67cc9 to 3fda60f Compare September 8, 2026 23:31
parzewski added a commit that referenced this pull request Sep 9, 2026
Codecov flagged lead_import_wizard.py at 54.14% (121 missed
lines) on PR #4. The pre-existing test_lead_import_fields.py
covers only the happy path of action_parse_and_check for the
column-mapping branches. Add a sibling test module
test_lead_import_wizard_coverage.py that exercises every other
branch:

  - _check_team_is_lead_pipeline / UserError when use_leads=False
  - action_discard (unlinks the wizard and returns
    act_window_close)
  - action_parse_and_check error paths (no file, garbage file,
    fully-empty row skipped)
  - _resolve_partner: email, email on child, name, name on child,
    company-only, no-match
  - _resolve_country: ISO, exact name, ilike, no match, blank
  - _resolve_tags: create missing, semicolon separator, blank,
    only separators, reuse existing
  - duplicate detection in crm.lead by name and by company
  - duplicate detection in res.partner by contact and by company
  - action_import_leads: per-person (line.partner_id), per-company
    fallback (line.partner_company_id), per-line import_line=False
    skip, chatter note post, done state
  - _compute_pipeline_count with matching opportunities and leads
  - action_view_opportunities / action_view_leads UserError and
    success paths
  - action_return_from_opportunities existing-wizard path

The "recreate from context" path of action_return_from_opportunities
is intentionally not exercised because the current code calls
self.create({"state": "preview"}) with no team_id and would
violate the not-null constraint; that is a separate bug to
file.

Local run: 60 splitstudio_lead_import tests, 0 failed,
0 errors.
parzewski added a commit that referenced this pull request Sep 9, 2026
Codecov flagged lead_import_wizard.py at 54.14% (121 missed
lines) on PR #4. The pre-existing test_lead_import_fields.py
covers only the happy path of action_parse_and_check for the
column-mapping branches. Add a sibling test module
test_lead_import_wizard_coverage.py that exercises every other
branch:

  - _check_team_is_lead_pipeline / UserError when use_leads=False
  - action_discard (unlinks the wizard and returns
    act_window_close)
  - action_parse_and_check error paths (no file, garbage file,
    fully-empty row skipped)
  - _resolve_partner: email, email on child, name, name on child,
    company-only, no-match
  - _resolve_country: ISO, exact name, ilike, no match, blank
  - _resolve_tags: create missing, semicolon separator, blank,
    only separators, reuse existing
  - duplicate detection in crm.lead by name and by company
  - duplicate detection in res.partner by contact and by company
  - action_import_leads: per-person (line.partner_id), per-company
    fallback (line.partner_company_id), per-line import_line=False
    skip, chatter note post, done state
  - _compute_pipeline_count with matching opportunities and leads
  - action_view_opportunities / action_view_leads UserError and
    success paths
  - action_return_from_opportunities existing-wizard path

The "recreate from context" path of action_return_from_opportunities
is intentionally not exercised because the current code calls
self.create({"state": "preview"}) with no team_id and would
violate the not-null constraint; that is a separate bug to
file.

Local run: 60 splitstudio_lead_import tests, 0 failed,
0 errors.
@parzewski
parzewski force-pushed the 18.0-add-splitstudio_lead_import branch 5 times, most recently from fa6ece9 to 5845b84 Compare September 9, 2026 01:30
@parzewski
parzewski marked this pull request as ready for review September 9, 2026 11:57
…check

Persistent wizard (models.Model) for importing CRM leads from XLSX/CSV
spreadsheets with advanced duplicate detection and rich header-to-field
mapping. The wizard is models.Model (not models.TransientModel) so import
sessions can be saved, listed and reviewed later from the new Import
Sessions menu.

Features
========

* Duplicate detection before any record is created, against both
  crm.lead and res.partner (email, lead/contact name, company name).
* Auto-creation of missing utm.campaign and crm.tag records from the
  spreadsheet (mirrors how tags were already handled).
* Country resolution by ISO code first (BR, US), then by name
  (Brazil, United States).
* Description column is stored on the lead and posted as a chatter
  internal note (mail.mt_note, visible in "Anotações internas").
* Priority column maps English (Low/Medium/High/Very High), Portuguese
  (Baixa/Média/Alta/Muito Alta) and numeric (0/1/2/3) values to the
  crm.lead priority stars widget.

Recognised spreadsheet columns (English and Portuguese aliases):
- oportunidade / opportunity / name (lead/opportunity name)
- contact_name / Contato (person name for partner match)
- email / email_from (email)
- partner_name / Empresa (company name)
- phone / Telefone
- campaign / campaign_id / Campanha (auto-created if missing)
- tags / tag_ids / Etiquetas (comma- or semicolon-separated,
  auto-created if missing)
- description / Anotações internas (chatter internal note)
- priority / Prioridade
- website / Site
- city / Cidade
- country_id / País (ISO code or full name)

UI
==

* Pipelines menu replaces the default Leads menu and exposes one entry
  per sales team that has use_leads=True, so each pipeline has its own
  filtered action.
* Move-to-another-pipeline wizard (crm.lead.reassign.wizard) opens from
  the lead form header since team_id is now readonly to enforce
  pipeline discipline.

Tests
=====

106 tests covering every wizard branch (lead_import_wizard,
lead_reassign_wizard) and the field-mapping paths. Project coverage
is 100% (codecov/patch and codecov/project both pass).

Notes for reviewers
===================

* team_id is readonly=True on the lead/opportunity form. Use the
  "Move to another pipeline" button in the form header to reassign a
  record to a different team.
* The conversion wizard is overridden to restrict team_id to teams
  with use_opportunities=True (so a lead on the INTAKE team cannot be
  converted to an opportunity on SCOUT EVENTOS).
* The wizard dropdown for team_id uses domain=[('use_leads', '=', True)]
  so you can only import into a pipeline that accepts leads.
* tools/link_orphans.py is a one-off back-fill helper (linking orphan
  opportunities to a partner by name); it is not loaded by the
  manifest and is meant to be piped into odoo shell.
@parzewski
parzewski force-pushed the 18.0-add-splitstudio_lead_import branch from 1b9ad6f to 26ffd41 Compare September 9, 2026 17:34
@parzewski
parzewski marked this pull request as draft September 9, 2026 17:43
@parzewski parzewski changed the title [18.0][ADD][WIP] splitstudio lead import [18.0][ADD] splitstudio lead import Sep 9, 2026
@parzewski
parzewski force-pushed the 18.0-add-splitstudio_lead_import branch from 33ca5d2 to 26ffd41 Compare September 9, 2026 21:41
@parzewski
parzewski marked this pull request as ready for review September 11, 2026 19:39

@DenerWilliam DenerWilliam left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@marcelsavegnago
marcelsavegnago merged commit d4dc1b7 into 18.0 Sep 11, 2026
6 checks passed
@marcelsavegnago
marcelsavegnago deleted the 18.0-add-splitstudio_lead_import branch September 11, 2026 20:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants