mirror of
https://github.com/inventree/InvenTree.git
synced 2025-12-16 09:18:10 +00:00
Remove code for ManufacturerPartParameter
This commit is contained in:
@@ -2,6 +2,53 @@
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
def convert_to_numeric_value(value: str, units: str):
|
||||
"""Convert a value (with units) to a numeric value.
|
||||
|
||||
Defaults to zero if the value cannot be converted.
|
||||
"""
|
||||
|
||||
import InvenTree.conversion
|
||||
|
||||
# Default value is null
|
||||
result = None
|
||||
|
||||
if units:
|
||||
try:
|
||||
result = InvenTree.conversion.convert_physical_value(value, units)
|
||||
result = float(result.magnitude)
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
result = float(value)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def remove_existing_parameters(apps, schema_editor):
|
||||
"""Remove any existing Parameter or ParameterTemplate objects from the database."""
|
||||
|
||||
Parameter = apps.get_model("common", "Parameter")
|
||||
ParameterTemplate = apps.get_model("common", "ParameterTemplate")
|
||||
|
||||
n_params = Parameter.objects.count()
|
||||
n_templates = ParameterTemplate.objects.count()
|
||||
|
||||
Parameter.objects.all().delete()
|
||||
ParameterTemplate.objects.all().delete()
|
||||
|
||||
if n_params > 0:
|
||||
print(f"Removed {n_params} existing Parameter instances.")
|
||||
|
||||
if n_templates > 0:
|
||||
print(f"Removed {n_templates} existing ParameterTemplate instances.")
|
||||
|
||||
assert Parameter.objects.count() == 0
|
||||
assert ParameterTemplate.objects.count() == 0
|
||||
|
||||
|
||||
def copy_part_parameters(apps, schema_editor):
|
||||
"""Forward migration: copy from PartParameterTemplate to ParameterTemplate."""
|
||||
@@ -29,14 +76,14 @@ def copy_part_parameters(apps, schema_editor):
|
||||
ParameterTemplate.objects.bulk_create(templates)
|
||||
print(f"\nMigrated {len(templates)} PartParameterTemplate instances.")
|
||||
|
||||
assert ParameterTemplate.objects.filter(model_type='part').count() == len(templates)
|
||||
assert ParameterTemplate.objects.filter().count() == len(templates)
|
||||
|
||||
# Next, copy PartParameter instances to Parameter instances
|
||||
parameters = []
|
||||
|
||||
for parameter in PartParameter.objects.all():
|
||||
# Find the corresponding ParameterTemplate
|
||||
template = ParameterTemplate.objects.get(name=parameter.template.name, model_type='part')
|
||||
template = ParameterTemplate.objects.get(name=parameter.template.name)
|
||||
|
||||
parameters.append(Parameter(
|
||||
template=template,
|
||||
@@ -56,6 +103,44 @@ def copy_part_parameters(apps, schema_editor):
|
||||
assert Parameter.objects.filter(model_type='part').count() == len(parameters)
|
||||
|
||||
|
||||
def copy_manufacturer_part_parameters(apps, schema_editor):
|
||||
"""Copy ManufacturerPartParameter to Parameter."""
|
||||
|
||||
ManufacturerPartParameter = apps.get_model("company", "ManufacturerPartParameter")
|
||||
Parameter = apps.get_model("common", "Parameter")
|
||||
ParameterTemplate = apps.get_model("common", "ParameterTemplate")
|
||||
|
||||
parameters = []
|
||||
|
||||
for parameter in ManufacturerPartParameter.objects.all():
|
||||
# Find the corresponding ParameterTemplate
|
||||
template = ParameterTemplate.objects.filter(name=parameter.template.name).first()
|
||||
|
||||
if not template:
|
||||
# A matching template does not exist - let's create one
|
||||
template = ParameterTemplate.objects.create(
|
||||
name=parameter.name,
|
||||
description='',
|
||||
units=parameter.units,
|
||||
checkbox=False
|
||||
)
|
||||
|
||||
parameters.append(Parameter(
|
||||
template=template,
|
||||
model_type='manufacturerpart',
|
||||
model_id=parameter.manufacturer_part.id,
|
||||
data=parameter.value,
|
||||
data_numeric=convert_to_numeric_value(parameter.value),
|
||||
note=parameter.note
|
||||
))
|
||||
|
||||
if len(parameters) > 0:
|
||||
Parameter.objects.bulk_create(parameters)
|
||||
print(f"\nMigrated {len(parameters)} ManufacturerPartParameter instances.")
|
||||
|
||||
assert Parameter.objects.filter(model_type='manufacturerpart').count() == len(parameters)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
@@ -64,10 +149,17 @@ class Migration(migrations.Migration):
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
remove_existing_parameters,
|
||||
reverse_code=migrations.RunPython.noop
|
||||
),
|
||||
migrations.RunPython(
|
||||
copy_part_parameters,
|
||||
reverse_code=migrations.RunPython.noop
|
||||
),
|
||||
# TODO: Data migration for existing ManufacturerPartParameter objects
|
||||
migrations.RunPython(
|
||||
copy_manufacturer_part_parameters,
|
||||
reverse_code=migrations.RunPython.noop
|
||||
)
|
||||
# TODO: Data migration for existing CategoryParameter objects
|
||||
]
|
||||
|
||||
@@ -740,6 +740,7 @@ class ParameterTemplateSerializer(
|
||||
)
|
||||
|
||||
|
||||
@register_importer()
|
||||
class ParameterSerializer(
|
||||
FilterableSerializerMixin, DataImportExportSerializerMixin, InvenTreeModelSerializer
|
||||
):
|
||||
|
||||
@@ -9,7 +9,6 @@ from .models import (
|
||||
Company,
|
||||
Contact,
|
||||
ManufacturerPart,
|
||||
ManufacturerPartParameter,
|
||||
SupplierPart,
|
||||
SupplierPriceBreak,
|
||||
)
|
||||
@@ -56,17 +55,6 @@ class ManufacturerPartAdmin(admin.ModelAdmin):
|
||||
autocomplete_fields = ('part', 'manufacturer')
|
||||
|
||||
|
||||
@admin.register(ManufacturerPartParameter)
|
||||
class ManufacturerPartParameterAdmin(admin.ModelAdmin):
|
||||
"""Admin class for ManufacturerPartParameter model."""
|
||||
|
||||
list_display = ('manufacturer_part', 'name', 'value')
|
||||
|
||||
search_fields = ['manufacturer_part__manufacturer__name', 'name', 'value']
|
||||
|
||||
autocomplete_fields = ('manufacturer_part',)
|
||||
|
||||
|
||||
@admin.register(SupplierPriceBreak)
|
||||
class SupplierPriceBreakAdmin(admin.ModelAdmin):
|
||||
"""Admin class for the SupplierPriceBreak model."""
|
||||
|
||||
@@ -24,7 +24,6 @@ from .models import (
|
||||
Company,
|
||||
Contact,
|
||||
ManufacturerPart,
|
||||
ManufacturerPartParameter,
|
||||
SupplierPart,
|
||||
SupplierPriceBreak,
|
||||
)
|
||||
@@ -32,7 +31,6 @@ from .serializers import (
|
||||
AddressSerializer,
|
||||
CompanySerializer,
|
||||
ContactSerializer,
|
||||
ManufacturerPartParameterSerializer,
|
||||
ManufacturerPartSerializer,
|
||||
SupplierPartSerializer,
|
||||
SupplierPriceBreakSerializer,
|
||||
@@ -217,56 +215,6 @@ class ManufacturerPartDetail(RetrieveUpdateDestroyAPI):
|
||||
serializer_class = ManufacturerPartSerializer
|
||||
|
||||
|
||||
class ManufacturerPartParameterFilter(FilterSet):
|
||||
"""Custom filterset for the ManufacturerPartParameterList API endpoint."""
|
||||
|
||||
class Meta:
|
||||
"""Metaclass options."""
|
||||
|
||||
model = ManufacturerPartParameter
|
||||
fields = ['name', 'value', 'units', 'manufacturer_part']
|
||||
|
||||
manufacturer = rest_filters.ModelChoiceFilter(
|
||||
queryset=Company.objects.all(), field_name='manufacturer_part__manufacturer'
|
||||
)
|
||||
|
||||
part = rest_filters.ModelChoiceFilter(
|
||||
queryset=part.models.Part.objects.all(), field_name='manufacturer_part__part'
|
||||
)
|
||||
|
||||
|
||||
class ManufacturerPartParameterOptions(OutputConfiguration):
|
||||
"""Available output options for the ManufacturerPartParameter endpoints."""
|
||||
|
||||
OPTIONS = [
|
||||
InvenTreeOutputOption(
|
||||
description='Include detailed information about the linked ManufacturerPart in the response',
|
||||
flag='manufacturer_part_detail',
|
||||
default=False,
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
class ManufacturerPartParameterList(
|
||||
SerializerContextMixin, ListCreateDestroyAPIView, OutputOptionsMixin
|
||||
):
|
||||
"""API endpoint for list view of ManufacturerPartParamater model."""
|
||||
|
||||
queryset = ManufacturerPartParameter.objects.all()
|
||||
serializer_class = ManufacturerPartParameterSerializer
|
||||
filterset_class = ManufacturerPartParameterFilter
|
||||
output_options = ManufacturerPartParameterOptions
|
||||
filter_backends = SEARCH_ORDER_FILTER
|
||||
search_fields = ['name', 'value', 'units']
|
||||
|
||||
|
||||
class ManufacturerPartParameterDetail(RetrieveUpdateDestroyAPI):
|
||||
"""API endpoint for detail view of ManufacturerPartParameter model."""
|
||||
|
||||
queryset = ManufacturerPartParameter.objects.all()
|
||||
serializer_class = ManufacturerPartParameterSerializer
|
||||
|
||||
|
||||
class SupplierPartFilter(FilterSet):
|
||||
"""API filters for the SupplierPartList endpoint."""
|
||||
|
||||
@@ -518,22 +466,6 @@ class SupplierPriceBreakDetail(SupplierPriceBreakMixin, RetrieveUpdateDestroyAPI
|
||||
|
||||
|
||||
manufacturer_part_api_urls = [
|
||||
path(
|
||||
'parameter/',
|
||||
include([
|
||||
path(
|
||||
'<int:pk>/',
|
||||
ManufacturerPartParameterDetail.as_view(),
|
||||
name='api-manufacturer-part-parameter-detail',
|
||||
),
|
||||
# Catch anything else
|
||||
path(
|
||||
'',
|
||||
ManufacturerPartParameterList.as_view(),
|
||||
name='api-manufacturer-part-parameter-list',
|
||||
),
|
||||
]),
|
||||
),
|
||||
path(
|
||||
'<int:pk>/',
|
||||
include([
|
||||
|
||||
@@ -473,6 +473,7 @@ class Address(InvenTree.models.InvenTreeModel):
|
||||
|
||||
class ManufacturerPart(
|
||||
InvenTree.models.InvenTreeAttachmentMixin,
|
||||
InvenTree.models.InvenTreeParameterMixin,
|
||||
InvenTree.models.InvenTreeBarcodeMixin,
|
||||
InvenTree.models.InvenTreeNotesMixin,
|
||||
InvenTree.models.InvenTreeMetadataModel,
|
||||
@@ -652,6 +653,7 @@ class SupplierPartManager(models.Manager):
|
||||
|
||||
class SupplierPart(
|
||||
InvenTree.models.InvenTreeAttachmentMixin,
|
||||
InvenTree.models.InvenTreeParameterMixin,
|
||||
InvenTree.models.MetadataMixin,
|
||||
InvenTree.models.InvenTreeBarcodeMixin,
|
||||
InvenTree.models.InvenTreeNotesMixin,
|
||||
|
||||
@@ -36,7 +36,6 @@ from .models import (
|
||||
Company,
|
||||
Contact,
|
||||
ManufacturerPart,
|
||||
ManufacturerPartParameter,
|
||||
SupplierPart,
|
||||
SupplierPriceBreak,
|
||||
)
|
||||
@@ -302,33 +301,6 @@ class ManufacturerPartSerializer(
|
||||
)
|
||||
|
||||
|
||||
@register_importer()
|
||||
class ManufacturerPartParameterSerializer(
|
||||
FilterableSerializerMixin, DataImportExportSerializerMixin, InvenTreeModelSerializer
|
||||
):
|
||||
"""Serializer for the ManufacturerPartParameter model."""
|
||||
|
||||
class Meta:
|
||||
"""Metaclass options."""
|
||||
|
||||
model = ManufacturerPartParameter
|
||||
|
||||
fields = [
|
||||
'pk',
|
||||
'manufacturer_part',
|
||||
'manufacturer_part_detail',
|
||||
'name',
|
||||
'value',
|
||||
'units',
|
||||
]
|
||||
|
||||
manufacturer_part_detail = enable_filter(
|
||||
ManufacturerPartSerializer(
|
||||
source='manufacturer_part', many=False, read_only=True, allow_null=True
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class SupplierPriceBreakBriefSerializer(
|
||||
FilterableSerializerMixin, InvenTreeModelSerializer
|
||||
):
|
||||
|
||||
@@ -3,7 +3,6 @@ import { Grid, Skeleton, Stack } from '@mantine/core';
|
||||
import {
|
||||
IconBuildingWarehouse,
|
||||
IconInfoCircle,
|
||||
IconList,
|
||||
IconPackages
|
||||
} from '@tabler/icons-react';
|
||||
import { useMemo } from 'react';
|
||||
@@ -33,6 +32,7 @@ import AttachmentPanel from '../../components/panels/AttachmentPanel';
|
||||
import NotesPanel from '../../components/panels/NotesPanel';
|
||||
import type { PanelType } from '../../components/panels/Panel';
|
||||
import { PanelGroup } from '../../components/panels/PanelGroup';
|
||||
import ParametersPanel from '../../components/panels/ParametersPanel';
|
||||
import { useManufacturerPartFields } from '../../forms/CompanyForms';
|
||||
import {
|
||||
useCreateApiFormModal,
|
||||
@@ -41,7 +41,6 @@ import {
|
||||
} from '../../hooks/UseForm';
|
||||
import { useInstance } from '../../hooks/UseInstance';
|
||||
import { useUserState } from '../../states/UserState';
|
||||
import ManufacturerPartParameterTable from '../../tables/purchasing/ManufacturerPartParameterTable';
|
||||
import { SupplierPartTable } from '../../tables/purchasing/SupplierPartTable';
|
||||
import { StockItemTable } from '../../tables/stock/StockItemTable';
|
||||
|
||||
@@ -161,18 +160,10 @@ export default function ManufacturerPartDetail() {
|
||||
icon: <IconInfoCircle />,
|
||||
content: detailsPanel
|
||||
},
|
||||
{
|
||||
name: 'parameters',
|
||||
label: t`Parameters`,
|
||||
icon: <IconList />,
|
||||
content: manufacturerPart?.pk ? (
|
||||
<ManufacturerPartParameterTable
|
||||
params={{ manufacturer_part: manufacturerPart.pk }}
|
||||
/>
|
||||
) : (
|
||||
<Skeleton />
|
||||
)
|
||||
},
|
||||
ParametersPanel({
|
||||
model_type: ModelType.manufacturerpart,
|
||||
model_id: manufacturerPart?.pk
|
||||
}),
|
||||
{
|
||||
name: 'stock',
|
||||
label: t`Received Stock`,
|
||||
|
||||
@@ -36,6 +36,7 @@ import AttachmentPanel from '../../components/panels/AttachmentPanel';
|
||||
import NotesPanel from '../../components/panels/NotesPanel';
|
||||
import type { PanelType } from '../../components/panels/Panel';
|
||||
import { PanelGroup } from '../../components/panels/PanelGroup';
|
||||
import ParametersPanel from '../../components/panels/ParametersPanel';
|
||||
import { useSupplierPartFields } from '../../forms/CompanyForms';
|
||||
import {
|
||||
useCreateApiFormModal,
|
||||
@@ -247,6 +248,10 @@ export default function SupplierPartDetail() {
|
||||
icon: <IconInfoCircle />,
|
||||
content: detailsPanel
|
||||
},
|
||||
ParametersPanel({
|
||||
model_type: ModelType.supplierpart,
|
||||
model_id: supplierPart?.pk
|
||||
}),
|
||||
{
|
||||
name: 'stock',
|
||||
label: t`Received Stock`,
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
|
||||
import { AddItemButton } from '@lib/components/AddItemButton';
|
||||
import {
|
||||
type RowAction,
|
||||
RowDeleteAction,
|
||||
RowEditAction
|
||||
} from '@lib/components/RowActions';
|
||||
import { ApiEndpoints } from '@lib/enums/ApiEndpoints';
|
||||
import { UserRoles } from '@lib/enums/Roles';
|
||||
import { apiUrl } from '@lib/functions/Api';
|
||||
import type { TableColumn } from '@lib/types/Tables';
|
||||
import { useManufacturerPartParameterFields } from '../../forms/CompanyForms';
|
||||
import {
|
||||
useCreateApiFormModal,
|
||||
useDeleteApiFormModal,
|
||||
useEditApiFormModal
|
||||
} from '../../hooks/UseForm';
|
||||
import { useTable } from '../../hooks/UseTable';
|
||||
import { useUserState } from '../../states/UserState';
|
||||
import { InvenTreeTable } from '../InvenTreeTable';
|
||||
|
||||
export default function ManufacturerPartParameterTable({
|
||||
params
|
||||
}: Readonly<{
|
||||
params: any;
|
||||
}>) {
|
||||
const table = useTable('manufacturer-part-parameter');
|
||||
const user = useUserState();
|
||||
|
||||
const tableColumns: TableColumn[] = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
accessor: 'name',
|
||||
title: t`Name`,
|
||||
sortable: true,
|
||||
switchable: false
|
||||
},
|
||||
{
|
||||
accessor: 'value',
|
||||
title: t`Value`,
|
||||
sortable: true,
|
||||
switchable: false
|
||||
},
|
||||
{
|
||||
accessor: 'units',
|
||||
title: t`Units`,
|
||||
sortable: false,
|
||||
switchable: true
|
||||
}
|
||||
];
|
||||
}, []);
|
||||
|
||||
const fields = useManufacturerPartParameterFields();
|
||||
|
||||
const [selectedParameter, setSelectedParameter] = useState<
|
||||
number | undefined
|
||||
>(undefined);
|
||||
|
||||
const createParameter = useCreateApiFormModal({
|
||||
url: ApiEndpoints.manufacturer_part_parameter_list,
|
||||
title: t`Add Parameter`,
|
||||
fields: fields,
|
||||
table: table,
|
||||
initialData: {
|
||||
manufacturer_part: params.manufacturer_part
|
||||
}
|
||||
});
|
||||
|
||||
const editParameter = useEditApiFormModal({
|
||||
url: ApiEndpoints.manufacturer_part_parameter_list,
|
||||
pk: selectedParameter,
|
||||
title: t`Edit Parameter`,
|
||||
fields: fields,
|
||||
table: table
|
||||
});
|
||||
|
||||
const deleteParameter = useDeleteApiFormModal({
|
||||
url: ApiEndpoints.manufacturer_part_parameter_list,
|
||||
pk: selectedParameter,
|
||||
title: t`Delete Parameter`,
|
||||
table: table
|
||||
});
|
||||
|
||||
const rowActions = useCallback(
|
||||
(record: any): RowAction[] => {
|
||||
return [
|
||||
RowEditAction({
|
||||
hidden: !user.hasChangeRole(UserRoles.purchase_order),
|
||||
onClick: () => {
|
||||
setSelectedParameter(record.pk);
|
||||
editParameter.open();
|
||||
}
|
||||
}),
|
||||
RowDeleteAction({
|
||||
hidden: !user.hasDeleteRole(UserRoles.purchase_order),
|
||||
onClick: () => {
|
||||
setSelectedParameter(record.pk);
|
||||
deleteParameter.open();
|
||||
}
|
||||
})
|
||||
];
|
||||
},
|
||||
[user]
|
||||
);
|
||||
|
||||
const tableActions = useMemo(() => {
|
||||
return [
|
||||
<AddItemButton
|
||||
key='add-parameter'
|
||||
tooltip={t`Add Parameter`}
|
||||
onClick={() => {
|
||||
createParameter.open();
|
||||
}}
|
||||
hidden={!user.hasAddRole(UserRoles.purchase_order)}
|
||||
/>
|
||||
];
|
||||
}, [user]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{createParameter.modal}
|
||||
{editParameter.modal}
|
||||
{deleteParameter.modal}
|
||||
<InvenTreeTable
|
||||
url={apiUrl(ApiEndpoints.manufacturer_part_parameter_list)}
|
||||
tableState={table}
|
||||
columns={tableColumns}
|
||||
props={{
|
||||
params: {
|
||||
...params
|
||||
},
|
||||
rowActions: rowActions,
|
||||
tableActions: tableActions
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user