Skip to content

[REM] base: company_type is dead for good #211043

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

tde-banana-odoo
Copy link
Contributor

@tde-banana-odoo tde-banana-odoo commented May 21, 2025

This PR removes the company_type field, which was previously used to distinguish
between 'Person' and 'Company' contacts.

The goal is to simplify the contact form and model by eliminating this distinction, as part
of an effort to streamline and simplify the contact information structure.

Changes in l10n* modules:

l10n_sa* : We'll now depend on 'l10n_sa_edi_additional_identification_scheme' field to
distinguish between a person and a company instead of 'is_company'.


l10n_tr* : Turkish electronic invoicing now uses VAT length to determine the schemeID:

  • 10-digit VAT → company (VKN)
  • 11-digit VAT → individual (TCKN)

l10n_es* : determine if a Spanish VAT number represents a legal entity based on
CIF structure: 1 letter + 8 digits (e.g., A12345678) → legal entity


l10n_ar* : determine a partner is a legal entity based on the AFIP identification type
and CUIT prefix.

Logic:
- AFIP code = '80' (CUIT)
- CUIT prefix in ('30', '33', '34', '51', '55') → considered a company

l10n_hu* : determine if a partner is a company based on VAT structure:

- VAT starts with 'HU' and is 10 digits, or
- Matches the Hungarian EU format: 8 digits - [2/4/5] - 2 digits

l10n_* : general : removed is_company / company_type from demo/tests

This change is in line with the broader initiative to remove legacy fields and make the model
more straightforward as possible.

It had a good run — well, not really — but it's dead for good now.

Removed fields:
base : is_company, company_type, commercial_company_name, company_name
crm : commercial_partner_id
survey : certifications_company_count
website_slides : slide_channel_company_count

Task-4714892

@robodoo
Copy link
Contributor

robodoo commented May 21, 2025

Pull request status dashboard

@C3POdoo C3POdoo added the RD research & development, internal work label May 21, 2025
@yagp-odoo yagp-odoo force-pushed the master-rem-base-sayonara-company-type-yagp branch 5 times, most recently from f35a33f to 4d2465e Compare May 28, 2025 07:14
Copy link
Contributor

@mrsr-odoo mrsr-odoo left a comment

Choose a reason for hiding this comment

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

Hello @yagp-odoo 👋 ,

Left some comments
But it feels strange that we sometimes use vat or parent_id in place of is_company(earlier it was easy to distinguish)
It might cause undesirable behaviour to the many flows
Can't we rely on parent_id only?

Thanks

@@ -184,7 +184,7 @@ def _compute_vies_valid(self):
partner.vies_valid = partner.parent_id.vies_valid
continue
try:
vies_valid = check_vies(partner.vat, timeout=10)
Copy link
Contributor

Choose a reason for hiding this comment

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

why do we remove the timeout here?

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, this was giving me unexpected argument 'timeout' on runbot,
Well Fixed now, the timeout was not present in test's setup class where it was patched. 🙃

@@ -2006,8 +1948,7 @@ def _prepare_customer_values(self, partner_name, is_company=False, parent_id=Fal
'website': self.website,
# company / hierarchy
'parent_id': parent_id,
'is_company': is_company,
'company_name': not is_company and not parent_id and self.partner_name,
'company_name': not parent_id and self.partner_name or self.partner_id.company_name,
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we do have to remove the company_name part as per "new request" in the pad

Copy link
Contributor

@yagp-odoo yagp-odoo May 29, 2025

Choose a reason for hiding this comment

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

the specs says remove this feature where we store a company name with a create btn, instead we should always create the company, so it's just asking me to remove the feature of creating company on button click...
by doing what I did above, we always have company_name, so that create_company won't be needed 🤔

Copy link
Contributor

Choose a reason for hiding this comment

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

IMO we should completely get rid of company_name as it will no longer used
what do you think ?

@@ -67,9 +67,6 @@ def res_partner_enrich_and_update_company(self, partner_id):
if not partner:
return {'error': _("This partner does not exist")}

if not partner.is_company:
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't we check parent_id here?

Copy link
Contributor

Choose a reason for hiding this comment

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

It was to check contact must be a company, but aren't we trying to get rid of that distinction?
Also, Company 1 > can have a Company 1.1 in child. So it will throw error there, right?
Maybe checking like Contact Must Have a VAT should be ok?

@yagp-odoo yagp-odoo force-pushed the master-rem-base-sayonara-company-type-yagp branch from 4d2465e to ab1ae35 Compare May 29, 2025 13:23
@yagp-odoo
Copy link
Contributor

Hello @mrsr-odoo 👋

But it feels strange that we sometimes use vat or parent_id in place of is_company
It might cause undesirable behavior to the many flows

Agreed it might cause unexpected outcome, but we mainly wants to check for VAT, as any registered company must have a VAT.

earlier it was easy to distinguish

Yes, but from what I understood, we're now wants to check its subject to VAT or not, not by distinguish its person or company.

Can't we rely on parent_id only?

In some cases YES, we can like for checking its root contact,..etc. A contact with False parent_id doesn't necessary have to be a Company, so checking VAT in most cases should do I think.

Though this can still be change when l10n modules come into play, Accounting Team/s may wants something different 🙃

@yagp-odoo yagp-odoo force-pushed the master-rem-base-sayonara-company-type-yagp branch 6 times, most recently from bdf5c9c to 8c6b21a Compare June 5, 2025 12:47
@tde-banana-odoo
Copy link
Contributor Author

@qdp-odoo I bet somehow this should interest you at some point. Draft and not finished in any way but hey.

@yagp-odoo yagp-odoo force-pushed the master-rem-base-sayonara-company-type-yagp branch 7 times, most recently from b85b531 to a813bc9 Compare June 12, 2025 13:03
Copy link
Contributor

@mrsr-odoo mrsr-odoo left a comment

Choose a reason for hiding this comment

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

Hello @yagp-odoo 👋 ,
Left some comments
Some conflicts to resolves
Thanks

@@ -22,6 +22,7 @@ registry.category("web_tour.tours").add("shop_checkout_address_ec", {
],
});

// TODO: Duplicate: Remove it in Master
Copy link
Contributor

Choose a reason for hiding this comment

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

I think they forget remove this file ?

@@ -307,7 +304,7 @@ def _find_existing_company(self, email):
if partner_iap:
return partner_iap.partner_id.sudo(False)

return request.env["res.partner"].search([("is_company", "=", True), ("email_normalized", "=ilike", "%" + search)], limit=1)
return request.env["res.partner"].search([('parent_id', '=', False), ("vat", "!=", False), ("email_normalized", "=ilike", "%" + search)], limit=1)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
return request.env["res.partner"].search([('parent_id', '=', False), ("vat", "!=", False), ("email_normalized", "=ilike", "%" + search)], limit=1)
return request.env["res.partner"].search([("parent_id", "=", False), ("vat", "!=", False), ("email_normalized", "=ilike", "%" + search)], limit=1)

Should we rely on both parent_id and vat ?
I think vat part is enough

Copy link
Contributor

Choose a reason for hiding this comment

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

There will be some cases where VAT is set but there will also be Parent ID.. as we're finding company here having parent_id False will ensure it's a company(in most cases) without a parent and has VAT.

Comment on lines +861 to +892
if values.get('parent_name') and not partner.parent_id:
# Create parent company if we got 'parent_name'
parent_values = dict(name=values.get('parent_name'), vat=partner.vat)
parent_values.update(self._convert_fields_to_values(self._address_fields()))
parent_company = self.create(parent_values)
# Set new company as parent
partner.write({
'parent_id': parent_company.id,
'child_ids': [Command.update(partner_id, dict(parent_id=parent_company.id)) for partner_id in partner.child_ids.ids]
})
Copy link
Contributor

Choose a reason for hiding this comment

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

parent_name is related to parent_id (non store field and readonly=True)
we should not use to create parent

Copy link
Contributor

@yagp-odoo yagp-odoo Jul 1, 2025

Choose a reason for hiding this comment

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

I made it stored and readonly=False field.
It will act in replacement of company_name. it will be not editable anywhere, but in cases like website form submit, we have a company input field, if user fill it, a company will be created and set as its parent.
Normally it wont affect related relation AFAIK.

PS: It's also used in crm

@yagp-odoo yagp-odoo force-pushed the master-rem-base-sayonara-company-type-yagp branch 5 times, most recently from 2a54909 to ba2b5a5 Compare July 1, 2025 09:28
@yagp-odoo yagp-odoo force-pushed the master-rem-base-sayonara-company-type-yagp branch 4 times, most recently from 3446344 to b3fc3cb Compare July 3, 2025 07:38
@yagp-odoo yagp-odoo force-pushed the master-rem-base-sayonara-company-type-yagp branch 5 times, most recently from c136e89 to 239bb89 Compare July 7, 2025 06:30
aj-fuentes added a commit to odoo-dev/upgrade-util that referenced this pull request Jul 7, 2025
@yagp-odoo yagp-odoo force-pushed the master-rem-base-sayonara-company-type-yagp branch from 239bb89 to f304cbb Compare July 7, 2025 12:43
@yagp-odoo yagp-odoo force-pushed the master-rem-base-sayonara-company-type-yagp branch 3 times, most recently from 635d680 to 9f5b2fd Compare July 8, 2025 13:41
@yagp-odoo yagp-odoo force-pushed the master-rem-base-sayonara-company-type-yagp branch from 9f5b2fd to 9539902 Compare July 17, 2025 09:48
yagp-odoo pushed a commit to odoo-dev/upgrade-util that referenced this pull request Jul 17, 2025
@yagp-odoo yagp-odoo force-pushed the master-rem-base-sayonara-company-type-yagp branch 4 times, most recently from 7800681 to 84b09bc Compare July 22, 2025 05:51
Introduced a computed boolean field 'l10n_ar_is_company' to determine if a
partner is a legal entity in Argentina, based on the AFIP identification type
and CUIT prefix.

This replaces reliance on the deprecated 'is_company' field, in line with
contact model simplification.

Logic:
- AFIP code = '80' (CUIT)
- CUIT prefix in ('30', '33', '34', '51', '55') → considered a company

Task-4714892
We'll now depend on 'l10n_sa_edi_additional_identification_scheme' field to
distinguish between a person and a company instead of 'is_company'.

Task-4714892
Turkish electronic invoicing now uses VAT length to determine the schemeID:
- 10-digit VAT → company (VKN)
- 11-digit VAT → individual (TCKN)

This replaces previous reliance on 'is_company', which has been removed as part
of the contact model simplification.

Task-4714892
Introduced '_l10n_es_is_legal_entity' to determine if a Spanish VAT number
represents a legal entity based on CIF structure:
- Format: 1 letter + 8 digits (e.g., A12345678)

This replaces the use of 'is_company, aligning with the contact model simplification.

Task-4714892
Introduced a computed field 'l10n_hu_is_company' to determine if a partner
is a company in Hungary, based on VAT structure.

Logic considers a partner a company if:
- VAT starts with 'HU' and is 10 digits, or
- Matches the Hungarian EU format: 8 digits - [2/4/5] - 2 digits

Task-4714892
Updates demo data and tests across various l10n_* modules to reflect
the removal of the 'is_company' field from the contact model.

Task-4714892
This commit removes the 'company_type' field, which was previously used to
distinguish between 'Person' and 'Company' contacts.
The goal is to simplify the contact form and model by eliminating this distinction,
as part of an effort to streamline and simplify the contact information structure.

This change is in line with the broader initiative to remove legacy fields and
make the model more straightforward as possible.

It had a good run — well, not really — but it's dead for good now.

Removed fields:
base  : is_company, company_type, commercial_company_name, company_name
crm : commercial_partner_id
survey : certifications_company_count
website_slides : slide_channel_company_count

Task-4714892
@yagp-odoo yagp-odoo force-pushed the master-rem-base-sayonara-company-type-yagp branch from 84b09bc to b89a968 Compare July 22, 2025 12:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
RD research & development, internal work
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants