diff --git a/CHANGELOG.md b/CHANGELOG.md index 1129b2ee0d..10e13b4cab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [#12900](https://github.com/Inventree/InvenTree/pull/12900) adds a UI feature `route` to the `UIMixin`, giving plugins the ability to register custom pages. - [#12911](https://github.com/inventree/InvenTree/pull/12911) adds global setting for default receive location against purchase orders - [#12914](https://github.com/inventree/InvenTree/pull/12914) adds the AllocateMixin, allowing plugins to customize automatic stock allocation for build orders and sales orders. +- [#13017](https://github.com/inventree/InvenTree/pull/13017) adds "internal" companies, which represent your own organization, along with a `INVENTREE_DEFAULT_INTERNAL_COMPANY` setting. The default internal company is available to all report templates as `internal_company`. - [#13016](https://github.com/inventree/InvenTree/pull/13016) adds a "contact" field to the SalesOrderShipment model and API endpoint. - [#13016](https://github.com/inventree/InvenTree/pull/13016) adds "phone" and "email" fields to the Address model and API endpoint. diff --git a/docs/docs/concepts/company.md b/docs/docs/concepts/company.md index b99128c7fb..c26a567215 100644 --- a/docs/docs/concepts/company.md +++ b/docs/docs/concepts/company.md @@ -14,6 +14,31 @@ External companies are represented by the *Company* database model. Each company !!! tip "Multi Purpose" A company may be allocated to multiple categories, for example, a company may be both a supplier and a customer. +### Internal Companies + +A company can also be marked as *internal*, meaning that it represents your own organization rather than an external business. Internal companies can have their own [contacts](#contacts) and [addresses](#addresses), just like any other company. + +More than one internal company can be defined - for example, if your organization operates as multiple legal entities, or from multiple sites. + +Internal companies are managed from the *Internal Companies* panel in the [Admin Center](../settings/admin.md). To mark an existing company as internal, edit the company and set the `is_internal` attribute to `True`. + +#### Default Internal Company + +The `INVENTREE_DEFAULT_INTERNAL_COMPANY` [global setting](../settings/global.md#server-settings) selects which internal company represents your organization by default. Only companies marked as internal can be selected. + +If this setting is not specified, and exactly one internal company exists, that company is used as the default. + +The default internal company is available to all [report and label templates](../report/context_variables.md) as the `internal_company` context variable. For example, to render your organization's name and primary address in a report header: + +```html +{% raw %} +{% if internal_company %} +

{{ internal_company.name }}

+

{{ internal_company.primary_address }}

+{% endif %} +{% endraw %} +``` + ### Edit Company To edit a company, click on the {{ icon("edit", color="blue", title="Edit Company") }} icon in the actions menu. Edit the company information, and then click on Submit. diff --git a/docs/docs/settings/global.md b/docs/docs/settings/global.md index ee5820408a..08273b91e2 100644 --- a/docs/docs/settings/global.md +++ b/docs/docs/settings/global.md @@ -23,6 +23,7 @@ Configuration of basic server settings: | ---- | ----------- | ------- | ----- | {{ globalsetting("INVENTREE_BASE_URL") }} {{ globalsetting("INVENTREE_COMPANY_NAME") }} +{{ globalsetting("INVENTREE_DEFAULT_INTERNAL_COMPANY") }} {{ globalsetting("INVENTREE_INSTANCE") }} {{ globalsetting("INVENTREE_INSTANCE_TITLE") }} {{ globalsetting("INVENTREE_INSTANCE_ID", default="Randomly generated value") }} diff --git a/src/backend/InvenTree/InvenTree/api_version.py b/src/backend/InvenTree/InvenTree/api_version.py index 4dc9a2b4d0..fc92f412d6 100644 --- a/src/backend/InvenTree/InvenTree/api_version.py +++ b/src/backend/InvenTree/InvenTree/api_version.py @@ -1,11 +1,16 @@ """InvenTree API version information.""" # InvenTree API version -INVENTREE_API_VERSION = 555 +INVENTREE_API_VERSION = 556 """Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" INVENTREE_API_TEXT = """ +v556 -> 2026-10-14 : https://github.com/inventree/InvenTree/pull/13017 + - Adds 'is_internal' field (and filter) to the Company API endpoint + - Adds 'INVENTREE_DEFAULT_INTERNAL_COMPANY' global setting + - Exposes 'model_filters' on the global and user settings API endpoints + v555 -> 2026-10-14 : https://github.com/inventree/InvenTree/pull/13016 - Adds "contact" field to the SalesOrderShipment model and API endpoint - Adds "phone" and "email" fields to the Address model and API endpoint diff --git a/src/backend/InvenTree/common/serializers.py b/src/backend/InvenTree/common/serializers.py index 4d198dc311..5b5cac1899 100644 --- a/src/backend/InvenTree/common/serializers.py +++ b/src/backend/InvenTree/common/serializers.py @@ -179,6 +179,7 @@ class GlobalSettingsSerializer(SettingsSerializer): 'units', 'choices', 'model_name', + 'model_filters', 'api_url', 'typ', 'read_only', @@ -226,6 +227,7 @@ class UserSettingsSerializer(SettingsSerializer): 'units', 'choices', 'model_name', + 'model_filters', 'api_url', 'typ', 'confirm', diff --git a/src/backend/InvenTree/common/setting/system.py b/src/backend/InvenTree/common/setting/system.py index 86e694c9fe..1ae86ef800 100644 --- a/src/backend/InvenTree/common/setting/system.py +++ b/src/backend/InvenTree/common/setting/system.py @@ -21,6 +21,24 @@ import report.helpers from common.setting.type import InvenTreeSettingsKeyType, SettingFlag +def validate_internal_company(value): + """Validate that the provided value is empty, or references an internal company.""" + from company.models import Company + + if value in [None, '']: + return + + try: + pk = int(value) + except (TypeError, ValueError): + raise ValidationError({'value': _('Invalid company')}) + + if not Company.objects.filter(pk=pk, is_internal=True).exists(): + raise ValidationError({ + 'value': _('Selected company must be marked as an internal company') + }) + + def validate_part_name_format(value): """Validate part name format. @@ -255,6 +273,14 @@ SYSTEM_SETTINGS: dict[str, InvenTreeSettingsKeyType] = { 'description': _('Internal company name'), 'default': 'My company name', }, + 'INVENTREE_DEFAULT_INTERNAL_COMPANY': { + 'name': _('Default internal company'), + 'description': _('Internal company which represents this organization'), + 'default': '', + 'model': 'company.company', + 'model_filters': {'is_internal': True}, + 'validator': validate_internal_company, + }, 'INVENTREE_BASE_URL': { 'name': _('Base URL'), 'description': _('Base URL for server instance'), diff --git a/src/backend/InvenTree/common/tests.py b/src/backend/InvenTree/common/tests.py index 96ee1e31ab..f215321666 100644 --- a/src/backend/InvenTree/common/tests.py +++ b/src/backend/InvenTree/common/tests.py @@ -756,6 +756,30 @@ class GlobalSettingsApiTest(InvenTreeAPITestCase): # There should be no user sessions now self.assertEqual(self.user.usersession_set.count(), 0) + def test_model_filters(self): + """Test that model-backed settings expose their model filters.""" + for key, model_name, filters in [ + ( + 'INVENTREE_DEFAULT_INTERNAL_COMPANY', + 'company.company', + {'is_internal': True}, + ), + ( + 'PURCHASEORDER_DEFAULT_RECEIVE_LOCATION', + 'stock.stocklocation', + {'structural': False}, + ), + ]: + url = reverse('api-global-setting-detail', kwargs={'key': key}) + response = self.get(url, expected_code=200) + + self.assertEqual(response.data['model_name'], model_name) + self.assertEqual(response.data['model_filters'], filters) + + # Settings without a model have no filters + url = reverse('api-global-setting-detail', kwargs={'key': 'INVENTREE_INSTANCE'}) + self.assertIsNone(self.get(url, expected_code=200).data['model_filters']) + def test_api_detail(self): """Test that we can access the detail view for a setting based on the .""" # These keys are invalid, and should return 404 diff --git a/src/backend/InvenTree/company/api.py b/src/backend/InvenTree/company/api.py index b48e581975..c942aabb9d 100644 --- a/src/backend/InvenTree/company/api.py +++ b/src/backend/InvenTree/company/api.py @@ -45,7 +45,14 @@ class CompanyFilter(FilterSet): """Metaclass options.""" model = Company - fields = ['is_customer', 'is_manufacturer', 'is_supplier', 'name', 'active'] + fields = [ + 'is_customer', + 'is_manufacturer', + 'is_supplier', + 'is_internal', + 'name', + 'active', + ] tag_name = common.filters.TagsFilter() diff --git a/src/backend/InvenTree/company/migrations/0083_company_is_internal.py b/src/backend/InvenTree/company/migrations/0083_company_is_internal.py new file mode 100644 index 0000000000..d85f362726 --- /dev/null +++ b/src/backend/InvenTree/company/migrations/0083_company_is_internal.py @@ -0,0 +1,22 @@ +# Generated by Django 5.2.17 on 2026-10-14 02:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("company", "0082_address_phone_email"), + ] + + operations = [ + migrations.AddField( + model_name="company", + name="is_internal", + field=models.BooleanField( + default=False, + help_text="Does this company represent your own organization?", + verbose_name="Is internal", + ), + ), + ] diff --git a/src/backend/InvenTree/company/models.py b/src/backend/InvenTree/company/models.py index c3b7f5f133..ecea00dc7a 100644 --- a/src/backend/InvenTree/company/models.py +++ b/src/backend/InvenTree/company/models.py @@ -27,6 +27,7 @@ import InvenTree.ready import InvenTree.validators import report.mixins from common.currency import currency_code_default +from common.settings import get_global_setting from InvenTree.fields import InvenTreeURLField, RoundingDecimalField from order.status_codes import PurchaseOrderStatusGroups @@ -91,6 +92,7 @@ class Company( - A supplier is a company from which parts can be purchased - A customer is a company to which parts can be sold - A manufacturer is a company which manufactures a raw good (they may or may not be a "supplier" also) + - An internal company represents your own organization (or one of its entities / sites) Attributes: @@ -107,6 +109,7 @@ class Company( is_customer: boolean value, is this company a customer is_supplier: boolean value, is this company a supplier is_manufacturer: boolean value, is this company a manufacturer + is_internal: boolean value, does this company represent your own organization currency_code: Specifies the default currency for the company tax_id: Tax ID for the company """ @@ -129,6 +132,29 @@ class Company( """Return the API URL associated with the Company model.""" return reverse('api-company-list') + @classmethod + def get_default_internal(cls) -> Optional['Company']: + """Return the default internal company for this InvenTree instance. + + - If the INVENTREE_DEFAULT_INTERNAL_COMPANY setting points to an internal company, return it + - Otherwise, if exactly one internal company exists, return it + - Otherwise, return None + """ + internal = cls.objects.filter(is_internal=True) + + if pk := get_global_setting( + 'INVENTREE_DEFAULT_INTERNAL_COMPANY', backup_value=None + ): + try: + if company := internal.filter(pk=int(pk)).first(): + return company + except (TypeError, ValueError): + pass + + companies = list(internal[:2]) + + return companies[0] if len(companies) == 1 else None + def report_context(self) -> CompanyReportContext: """Generate a dict of context data to provide to the reporting framework.""" return { @@ -212,6 +238,12 @@ class Company( help_text=_('Does this company manufacture parts?'), ) + is_internal = models.BooleanField( + default=False, + verbose_name=_('Is internal'), + help_text=_('Does this company represent your own organization?'), + ) + currency = models.CharField( max_length=3, verbose_name=_('Currency'), diff --git a/src/backend/InvenTree/company/serializers.py b/src/backend/InvenTree/company/serializers.py index 586956b6a5..35d7b99acd 100644 --- a/src/backend/InvenTree/company/serializers.py +++ b/src/backend/InvenTree/company/serializers.py @@ -146,6 +146,7 @@ class CompanySerializer( 'is_customer', 'is_manufacturer', 'is_supplier', + 'is_internal', 'parts_supplied', 'parts_manufactured', 'primary_address', diff --git a/src/backend/InvenTree/company/test_api.py b/src/backend/InvenTree/company/test_api.py index a8139b8b02..04f8f7fb2c 100644 --- a/src/backend/InvenTree/company/test_api.py +++ b/src/backend/InvenTree/company/test_api.py @@ -71,6 +71,35 @@ class CompanyTest(InvenTreeAPITestCase): response = self.get(url, data) self.assertEqual(len(response.data), 2) + def test_company_internal(self): + """Test the 'is_internal' field and filter.""" + url = reverse('api-company-list') + + self.assertEqual(len(self.get(url, {'is_internal': True}).data), 0) + + response = self.post( + url, + {'name': 'Our Company', 'is_internal': True, 'is_supplier': False}, + expected_code=201, + ) + self.assertTrue(response.data['is_internal']) + pk = response.data['pk'] + + response = self.get(url, {'is_internal': True}) + self.assertEqual(len(response.data), 1) + self.assertEqual(response.data[0]['pk'], pk) + + self.assertEqual(len(self.get(url, {'is_internal': False}).data), 3) + + # Only an internal company can be selected as the default + setting_url = reverse( + 'api-global-setting-detail', + kwargs={'key': 'INVENTREE_DEFAULT_INTERNAL_COMPANY'}, + ) + + self.patch(setting_url, {'value': self.acme.pk}, expected_code=400) + self.patch(setting_url, {'value': pk}, expected_code=200) + def test_company_detail(self): """Tests for the Company detail endpoint.""" url = reverse('api-company-detail', kwargs={'pk': self.acme.pk}) diff --git a/src/backend/InvenTree/company/tests.py b/src/backend/InvenTree/company/tests.py index 3187b0ee36..8bc8af01d5 100644 --- a/src/backend/InvenTree/company/tests.py +++ b/src/backend/InvenTree/company/tests.py @@ -5,6 +5,8 @@ import os from django.core.exceptions import ValidationError from django.test import TestCase +from common.models import InvenTreeSetting +from common.settings import set_global_setting from part.models import Part from .models import ( @@ -159,6 +161,57 @@ class ContactSimpleTest(TestCase): self.assertEqual(Contact.objects.count(), 0) +class InternalCompanyTest(TestCase): + """Unit tests for internal company support.""" + + SETTING = 'INVENTREE_DEFAULT_INTERNAL_COMPANY' + + @classmethod + def setUpTestData(cls): + """Create some companies to work with.""" + super().setUpTestData() + + cls.supplier = Company.objects.create(name='Supplier', is_supplier=True) + cls.hq = Company.objects.create(name='HQ', is_supplier=False, is_internal=True) + + def test_default(self): + """Test the Company.get_default_internal() helper.""" + set_global_setting(self.SETTING, '') + + # A single internal company is used as the default + self.assertEqual(Company.get_default_internal(), self.hq) + + # Multiple internal companies, with no setting, is ambiguous + site = Company.objects.create(name='Site', is_supplier=False, is_internal=True) + self.assertIsNone(Company.get_default_internal()) + + # The setting selects between them + set_global_setting(self.SETTING, site.pk) + self.assertEqual(Company.get_default_internal(), site) + + # A setting which no longer points to an internal company is ignored + site.is_internal = False + site.save() + self.assertEqual(Company.get_default_internal(), self.hq) + + # No internal companies at all + Company.objects.filter(is_internal=True).update(is_internal=False) + self.assertIsNone(Company.get_default_internal()) + + def test_setting_validation(self): + """The setting may only reference an internal company.""" + setting = InvenTreeSetting.get_setting_object(self.SETTING, create=True) + + for value in [self.supplier.pk, 99999, 'abc']: + setting.value = value + with self.assertRaises(ValidationError): + setting.full_clean() + + for value in ['', self.hq.pk]: + setting.value = value + setting.full_clean() + + class AddressTest(TestCase): """Unit tests for the Address model.""" diff --git a/src/backend/InvenTree/importer/tests.py b/src/backend/InvenTree/importer/tests.py index 04757fbeac..706c44b203 100644 --- a/src/backend/InvenTree/importer/tests.py +++ b/src/backend/InvenTree/importer/tests.py @@ -45,7 +45,7 @@ class ImporterTest(ImporterMixin, InvenTreeTestCase): session.extract_columns() - self.assertEqual(session.column_mappings.count(), 13) + self.assertEqual(session.column_mappings.count(), 14) # Check some of the field mappings for field, col in [ diff --git a/src/backend/InvenTree/report/models.py b/src/backend/InvenTree/report/models.py index b8ec7dadf2..b8cde506e3 100644 --- a/src/backend/InvenTree/report/models.py +++ b/src/backend/InvenTree/report/models.py @@ -30,6 +30,7 @@ import report.helpers import report.validators from common.models import DataOutput, RenderChoices, UpdatedUserMixin from common.settings import get_global_setting +from company.models import Company from InvenTree.helpers_model import get_base_url from InvenTree.models import MetadataMixin from plugin import InvenTreePlugin, PluginMixinEnum @@ -158,6 +159,7 @@ class BaseContextExtension(TypedDict): template_name: Name of the report template template_revision: Revision of the report template user: User who is creating the report (if available) + internal_company: The default internal company (if defined) which represents this organization report_vars: Private dict for the {% get_var %} / {% set_var %} template tags """ @@ -169,6 +171,7 @@ class BaseContextExtension(TypedDict): template_name: str template_revision: int user: Optional[AbstractUser] + internal_company: Optional[Company] report_vars: dict @@ -410,6 +413,13 @@ class ReportTemplateBase( """Return a filter dict which can be applied to the target model.""" return report.validators.validate_filters(self.filters, model=self.get_model()) + def get_internal_company(self) -> Optional[Company]: + """Return the default internal company, cached for the lifetime of this template instance.""" + if not hasattr(self, '_internal_company'): + self._internal_company = Company.get_default_internal() + + return self._internal_company + def base_context(self, **kwargs) -> BaseContextExtension: """Return base context data (available to all templates).""" return { @@ -421,6 +431,7 @@ class ReportTemplateBase( 'template_name': self.name, 'template_revision': self.revision, 'user': kwargs.get('user'), + 'internal_company': self.get_internal_company(), # A private, per-render dict for the {% get_var %} / {% set_var %} tags. # This is discarded once rendering of *this* instance completes, # and is never shared between instances, reports, or requests. diff --git a/src/backend/InvenTree/report/tests.py b/src/backend/InvenTree/report/tests.py index 9a7f9c7619..d7286cbd03 100644 --- a/src/backend/InvenTree/report/tests.py +++ b/src/backend/InvenTree/report/tests.py @@ -67,6 +67,23 @@ class ReportTest(InvenTreeAPITestCase): return super().setUp() + def test_internal_company_context(self): + """Test that the default internal company is available in the base context.""" + from company.models import Company + + template = ReportTemplate.objects.first() + self.assertIsNone(template.base_context()['internal_company']) + + company = Company.objects.create( + name='Our Company', is_supplier=False, is_internal=True + ) + + # Value is cached against the template instance + self.assertIsNone(template.base_context()['internal_company']) + + template = ReportTemplate.objects.get(pk=template.pk) + self.assertEqual(template.base_context()['internal_company'], company) + def test_list_endpoint(self): """Test that the LIST endpoint works for each report.""" url = reverse('api-report-template-list') diff --git a/src/frontend/src/forms/CompanyForms.tsx b/src/frontend/src/forms/CompanyForms.tsx index 4323a6b200..48db3c7368 100644 --- a/src/frontend/src/forms/CompanyForms.tsx +++ b/src/frontend/src/forms/CompanyForms.tsx @@ -189,6 +189,7 @@ export function companyFields({ is_supplier: {}, is_manufacturer: {}, is_customer: {}, + is_internal: {}, active: {}, duplicate: DuplicateField({ originalId: duplicateCompanyId, diff --git a/src/frontend/src/functions/icons.tsx b/src/frontend/src/functions/icons.tsx index 13e9f9ed79..e34723e9a3 100644 --- a/src/frontend/src/functions/icons.tsx +++ b/src/frontend/src/functions/icons.tsx @@ -10,6 +10,7 @@ import { IconBrandTelegram, IconBuilding, IconBuildingFactory2, + IconBuildingSkyscraper, IconBuildingStore, IconBusinessplan, IconCalendar, @@ -158,6 +159,7 @@ const icons: InvenTreeIconType = { manufacturers: IconBuildingFactory2, suppliers: IconBuilding, customers: IconBuildingStore, + internal_company: IconBuildingSkyscraper, purchase_orders: IconShoppingCart, return_orders: IconTruckReturn, transfer_orders: IconTransfer, diff --git a/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx b/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx index df3c90b5d2..232150d2bd 100644 --- a/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx +++ b/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx @@ -4,6 +4,7 @@ import type { PanelGroupType, PanelType } from '@lib/types/Panel'; import { t } from '@lingui/core/macro'; import { Stack } from '@mantine/core'; import { + IconBuilding, IconCoins, IconCpu, IconDevicesPc, @@ -35,6 +36,7 @@ import { PanelGroup } from '../../../../components/panels/PanelGroup'; import { GlobalSettingList } from '../../../../components/settings/SettingList'; import { Loadable } from '../../../../functions/loading'; import { useUserState } from '../../../../states/UserState'; +import { CompanyTable } from '../../../../tables/company/CompanyTable'; import ParameterTemplateTable from '../../../../tables/general/ParameterTemplateTable'; import SelectionListTable from '../../../../tables/settings/SelectionListTable'; @@ -176,6 +178,17 @@ export default function AdminCenter() { icon: , content: }, + { + name: 'companies', + label: t`Companies`, + icon: , + content: ( + + + + + ) + }, { name: 'currencies', label: t`Currencies`, @@ -299,6 +312,7 @@ export default function AdminCenter() { 'barcode-history', 'background', 'errors', + 'companies', 'currencies', 'email' ] diff --git a/src/frontend/src/pages/Index/Settings/SystemSettings.tsx b/src/frontend/src/pages/Index/Settings/SystemSettings.tsx index fec3611353..e9b6227e1f 100644 --- a/src/frontend/src/pages/Index/Settings/SystemSettings.tsx +++ b/src/frontend/src/pages/Index/Settings/SystemSettings.tsx @@ -47,6 +47,7 @@ export default function SystemSettings() { keys={[ 'INVENTREE_BASE_URL', 'INVENTREE_COMPANY_NAME', + 'INVENTREE_DEFAULT_INTERNAL_COMPANY', 'INVENTREE_INSTANCE', 'INVENTREE_INSTANCE_TITLE', 'INVENTREE_INSTANCE_ID', diff --git a/src/frontend/src/pages/company/CompanyDetailsPanel.tsx b/src/frontend/src/pages/company/CompanyDetailsPanel.tsx index b98d67515c..1de2ef55cb 100644 --- a/src/frontend/src/pages/company/CompanyDetailsPanel.tsx +++ b/src/frontend/src/pages/company/CompanyDetailsPanel.tsx @@ -83,6 +83,13 @@ export function CompanyDetailsPanel({ name: 'is_customer', label: t`Customer`, icon: 'customers' + }, + { + type: 'boolean', + name: 'is_internal', + label: t`Internal`, + icon: 'internal_company', + hidden: !instance?.is_internal } ]; diff --git a/src/frontend/src/tables/company/CompanyTable.tsx b/src/frontend/src/tables/company/CompanyTable.tsx index f4705f363b..0ede197eee 100644 --- a/src/frontend/src/tables/company/CompanyTable.tsx +++ b/src/frontend/src/tables/company/CompanyTable.tsx @@ -27,6 +27,13 @@ import { usePreviewDrawerState } from '../../states/PreviewDrawerState'; import { useUserSettingsState } from '../../states/SettingsStates'; import { useUserState } from '../../states/UserState'; +type CompanyTableType = + | 'all' + | 'internal' + | 'supplier' + | 'manufacturer' + | 'customer'; + /** * A table which displays a list of company records, * based on the provided filter parameters @@ -34,10 +41,12 @@ import { useUserState } from '../../states/UserState'; export function CompanyTable({ companyType, params, + initialData, path }: Readonly<{ - companyType?: string; + companyType?: CompanyTableType; params?: any; + initialData?: any; path?: string; }>) { const table = useTable(`company-${companyType ?? 'index'}`, { @@ -77,18 +86,54 @@ export function CompanyTable({ sortable: true, switchable: true }), + BooleanColumn({ + accessor: 'is_supplier', + filter: 'is_supplier', + title: t`Supplier`, + sortable: true, + switchable: true, + hidden: companyType === 'supplier', + defaultVisible: false + }), + BooleanColumn({ + accessor: 'is_manufacturer', + filter: 'is_manufacturer', + title: t`Manufacturer`, + sortable: true, + switchable: true, + hidden: companyType === 'manufacturer', + defaultVisible: false + }), + BooleanColumn({ + accessor: 'is_customer', + filter: 'is_customer', + title: t`Customer`, + sortable: true, + switchable: true, + hidden: companyType === 'customer', + defaultVisible: false + }), + BooleanColumn({ + accessor: 'is_internal', + filter: 'is_internal', + title: t`Internal`, + sortable: true, + switchable: true, + hidden: companyType === 'internal', + defaultVisible: false + }), { accessor: 'website', sortable: false } ]; - }, []); + }, [companyType]); const newCompany = useCreateApiFormModal({ url: ApiEndpoints.company_list, title: t`Add Company`, fields: companyFields(), - initialData: params, + initialData: initialData ?? params, follow: true, modelType: ModelType.company, keepOpenOption: true @@ -126,6 +171,11 @@ export function CompanyTable({ label: t`Customer`, description: t`Show companies which are customers` }, + { + name: 'is_internal', + label: t`Internal`, + description: t`Show companies which represent your own organization` + }, TagsFilter({ modelType: ModelType.company }) ]; }, []);