[16.0][ADD] partner_archive_propagate#2212
Conversation
8d88e95 to
aacee86
Compare
aacee86 to
96daaf3
Compare
| string="Archive Contact and Children" | ||
| class="oe_highlight" | ||
| attrs="{ | ||
| 'invisible': ['|', ('active', '=', False), ('show_prop_wizard_button', '=', False)] |
There was a problem hiding this comment.
or maybe child_ids = [], and remove show_prop_wizard_button field altogether
|
I tested this on runboat, and the button works nicely:
|
96daaf3 to
818aa69
Compare
|
|
||
| def write(self, vals): | ||
| """Enable (un)archiving propagation""" | ||
| archiving = "active" in vals and vals.get("active") is False |
There was a problem hiding this comment.
Works, but can be shortened:
archiving = vals.get("active", True) is False
and similar for unarchiving
unarchiving = vals.get("active", False) is True
818aa69 to
19b220a
Compare
| "line_ids": [(0, 0, {"partner_id": p.id}) for p in archivable], | ||
| } | ||
| ) | ||
| self._notify_skipped_partners(unarchivable) |
There was a problem hiding this comment.
I think this notification comes to early, as the user can still cancel the whole action in the wizard.
There was a problem hiding this comment.
@ntsirintanis I think you missed this remark...
NL66278
left a comment
There was a problem hiding this comment.
Looks great in general and very nice to have so many unit tests. There is one remark on statements that can be more concise, and one on a message that I think comes to early.
19b220a to
90baf48
Compare
|
The lacking coverage could be solved by creating a wizard for some partners that are unarchivable and then checking that in you get a message in the confirmation window: https://app.codecov.io/gh/OCA/partner-contact/pull/2212?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=checks&utm_campaign=pr+comments&utm_term=OCA |
6797e5b to
7d8c820
Compare
7d8c820 to
0134223
Compare
|
@ntsirintanis Everything green, that is great. You should still delete lines 88 - 97 of the test (and then unindent 98). As this is a branch never taken. |
0134223 to
9d3bc2d
Compare
NL66278
left a comment
There was a problem hiding this comment.
👍 Great work and fully covered with tests!
| class ResPartner(models.Model): | ||
| _inherit = "res.partner" | ||
|
|
||
| propagated_archive = fields.Boolean( |
There was a problem hiding this comment.
@ntsirintanis It occured to me that unarchiving could be made more efficient (and more traceable), when not having a boolean here, but the id of the partner that was the source of the propagation.
So replace this field with a Many2one to res.partner called propagated_from_id. Now when unarchiving it would be much faster to just find all the partners that where archived because this partners archiving had been propagated (and that still are archived).
The beauty of it would be that with the new module that archives through relations, nothing extra would need to be done to propagate the unarchiving to those partners as well, it would already be covered in this module.
| for partner in self: | ||
| partner.show_prop_wizard_button = bool(partner.child_ids) | ||
|
|
||
| def write(self, vals): |
There was a problem hiding this comment.
Some extra streamlining with partner_multi_relation_archive_propagate(pmrap) is possible.
In pmrap you already selected archiving_companies and unarchiving_companies. You can do the same here, but with no selection on company, you will have archiving_partners or unarchiving partners (never both, often none).
Then from this method:
if archiving_partners:
archiving_partners._archive_propagate()
elif unarchiving_partners:
unarchiving_partners._unarchive_propagate()
The extra functionality in pmrap to propagate archiving to related partners if the archived partner is a company can be added by overriding the _archive_propagate() method then. Then in pmrap you do not need to overwrite the write() method at all.
If you follow my suggestion to replace the boolean propagated_archive with the id of the archiving source partner), you will need to do nothing for unarchiving in pmrap,
155031e to
6c2833a
Compare
| unarchiving_partners = self.browse() | ||
| if "active" in vals: | ||
| if vals["active"] is False: | ||
| archiving_partners = self |
There was a problem hiding this comment.
self filtered on only active partners
| if vals["active"] is False: | ||
| archiving_partners = self | ||
| elif vals["active"] is True: | ||
| unarchiving_partners = self |
There was a problem hiding this comment.
self filtered on only archived partners
| unarchiving_partners._unarchive_propagate() | ||
| return res | ||
|
|
||
| def _archive_propagate(self, from_ui=False): |
There was a problem hiding this comment.
As the method has two independent branches, just split it in two methods, that then actualy do not need any argument (apart from self).
| Only touches partners where propagated_from_id points to the unarchived | ||
| parent, and that are currently inactive. | ||
| """ | ||
| for partner in self: |
There was a problem hiding this comment.
No need for a loop. Change the first line in the domain to ("propagated_from_id", "in", self.ids),
NL66278
left a comment
There was a problem hiding this comment.
Nice, but few changes still needed.
6c2833a to
db963e8
Compare
NL66278
left a comment
There was a problem hiding this comment.
👍 LGTM And well tested both in unit test and IRL.
marcos-mendez
left a comment
There was a problem hiding this comment.
Automated Review -- Tests Failed
1. Root Cause
The test failure is caused by a database connection error (Connection to the database failed) during the Odoo server startup, which indicates an issue in the test environment setup or configuration, not in the module's logic itself.
2. Suggested Fix
The error occurs before any module code is executed. Ensure the test environment is properly configured with a valid database connection. This is likely due to a misconfiguration in runboat or CI setup, and not a code bug in partner_archive_propagate.
However, to make the module more robust:
- In
res_partner.py, line ~173,_force_non_ui()method should handle potentialKeyErrororConfigParameteraccess errors gracefully.def _force_non_ui(self): """Read system setting controlling external propagation.""" try: return self.env["ir.config_parameter"].sudo().get_param( "partner_archive_propagate.force_outside_ui", default="0" ) in ("1", "true", "True") except Exception: return False # fallback to disable propagation if config is missing
3. Additional Code Issues
- Line 130 in
res_partner.py: The method_split_archivable_unarchivable_user()is inefficient as it loops through all partners individually. It should be optimized usingsudo().read(['user_ids'])or batch queries for better performance. - Missing
@api.modeldecorator in_force_non_ui()method — though not causing runtime error, it's semantically incorrect and may mislead developers expecting model-level behavior.
4. Test Improvements
Add the following test cases in a TransactionCase or SavepointCase:
Test Cases:
-
Test propagation on archive via UI (wizard):
- Create a parent partner with children (contact and non-contact).
- Call
action_archive_with_contacts()and verify:- Non-contact children are archived silently.
- Contact children appear in wizard.
- Active users prevent archiving of their linked partners.
propagated_from_idis correctly set.
-
Test propagation on external archive (non-UI):
- Enable
force_outside_ui. - Archive a parent partner via
write({'active': False}). - Verify all descendants are archived with correct
propagated_from_id.
- Enable
-
Test unarchive propagation:
- Archive a parent partner with descendants.
- Unarchive the parent.
- Verify descendants are also unarchived and
propagated_from_idcleared.
-
Test default behavior (without force):
- Archive a parent without enabling
force_outside_ui. - Ensure no propagation happens unless triggered by UI.
- Archive a parent without enabling
Use @tag('post_install') for integration tests and @tag('fast') for unit-level tests.
These tests should be added to tests/test_partner_archive_propagate.py.
⏰ PR Aging Alert
This PR by @ntsirintanis has been open for 123 days (4 months).
💤 Last activity was 33 days ago.
Every ignored PR is a contributor who might not come back. Review time matters. (OCA Aging Report)
Reciprocal Review Request
Hi everyone! I found some test failures on this PR and left detailed feedback above. I am happy to discuss or help debug. In the meantime, if any of you get a chance, I would appreciate a look at my open PR(s):
My open PRs across OCA:
- server-tools#3554 [MIG] datetime_formatter: Migration to 18.0
- server-tools#3548 [18.0][MIG] base_kanban_stage: Migration to 18.0
- hr-attendance#262 [16.0][ADD] Hr_attendance_idsecure: iDSecure (ControliD) attendance integration
- stock-logistics-workflow#2276 [16.0][ADD] stock_move_line_devaluation
- stock-logistics-workflow#2275 [16.0][ADD] Stock move line analytic account
- stock-logistics-workflow#2268 [16.0][ADD] stock_move_line_picking_partner
- purchase-workflow#2694 [16.0][IMP]Purchase workflow added to review state & exception fix
Reviewing each other's work helps the whole community move forward. Thank you!
Environment via OCA Neural Reviewer: Minikube + K8s Job + oca-ci/py3.10-odoo16.0 | Odoo 16.0
Automated review by OCA Neural Reviewer + qwen3-coder:30b
This module extends the native archiving mechanism for partners.
When archiving a company or parent contact, it will also handle its descendants
according to business rules — with user control and safeguards.
Features
(imports, RPC, automated jobs, etc.).