# Generated by Django 5.2.8 on 2026-01-13 00:43

from collections import defaultdict
from decimal import Decimal

import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models


def create_unit_definitions(apps, schema_editor):
    QuantityOfMeasure = apps.get_model('bom', 'QuantityOfMeasure')
    UnitDefinition = apps.get_model('bom', 'UnitDefinition')

    # Voltage
    voltage = QuantityOfMeasure.objects.create(name='Voltage')
    UnitDefinition.objects.create(name='Volt', symbol='V', quantity_of_measure=voltage, base_multiplier=Decimal('1.0'))
    UnitDefinition.objects.create(name='Millivolt', symbol='mV', quantity_of_measure=voltage,
                                  base_multiplier=Decimal('0.001'))
    UnitDefinition.objects.create(name='Microvolt', symbol='uV', quantity_of_measure=voltage,
                                  base_multiplier=Decimal('0.000001'))
    UnitDefinition.objects.create(name='Kilovolt', symbol='kV', quantity_of_measure=voltage,
                                  base_multiplier=Decimal('1000.0'))
    UnitDefinition.objects.create(name='Megavolt', symbol='MV', quantity_of_measure=voltage,
                                  base_multiplier=Decimal('1000000.0'))

    # Current
    current = QuantityOfMeasure.objects.create(name='Current')
    UnitDefinition.objects.create(name='Ampere', symbol='A', quantity_of_measure=current,
                                  base_multiplier=Decimal('1.0'))
    UnitDefinition.objects.create(name='Milliampere', symbol='mA', quantity_of_measure=current,
                                  base_multiplier=Decimal('0.001'))
    UnitDefinition.objects.create(name='Microampere', symbol='uA', quantity_of_measure=current,
                                  base_multiplier=Decimal('0.000001'))
    UnitDefinition.objects.create(name='Kiloampere', symbol='kA', quantity_of_measure=current,
                                  base_multiplier=Decimal('1000.0'))
    UnitDefinition.objects.create(name='Megaampere', symbol='MA', quantity_of_measure=current,
                                  base_multiplier=Decimal('1000000.0'))

    # Resistance
    resistance = QuantityOfMeasure.objects.create(name='Resistance')
    UnitDefinition.objects.create(name='Ohm', symbol='Ω', quantity_of_measure=resistance,
                                  base_multiplier=Decimal('1.0'))
    UnitDefinition.objects.create(name='Milliohm', symbol='mΩ', quantity_of_measure=resistance,
                                  base_multiplier=Decimal('0.001'))
    UnitDefinition.objects.create(name='Kiloohm', symbol='kΩ', quantity_of_measure=resistance,
                                  base_multiplier=Decimal('1000.0'))
    UnitDefinition.objects.create(name='Megaohm', symbol='MΩ', quantity_of_measure=resistance,
                                  base_multiplier=Decimal('1000000.0'))

    # Capacitance
    capacitance = QuantityOfMeasure.objects.create(name='Capacitance')
    UnitDefinition.objects.create(name='Farad', symbol='F', quantity_of_measure=capacitance,
                                  base_multiplier=Decimal('1.0'))
    UnitDefinition.objects.create(name='Millifarad', symbol='mF', quantity_of_measure=capacitance,
                                  base_multiplier=Decimal('0.001'))
    UnitDefinition.objects.create(name='Microfarad', symbol='uF', quantity_of_measure=capacitance,
                                  base_multiplier=Decimal('0.000001'))
    UnitDefinition.objects.create(name='Nanofarad', symbol='nF', quantity_of_measure=capacitance,
                                  base_multiplier=Decimal('0.000000001'))
    UnitDefinition.objects.create(name='Picofarad', symbol='pF', quantity_of_measure=capacitance,
                                  base_multiplier=Decimal('0.000000000001'))

    # Inductance
    inductance = QuantityOfMeasure.objects.create(name='Inductance')
    UnitDefinition.objects.create(name='Henry', symbol='H', quantity_of_measure=inductance,
                                  base_multiplier=Decimal('1.0'))
    UnitDefinition.objects.create(name='Millihenry', symbol='mH', quantity_of_measure=inductance,
                                  base_multiplier=Decimal('0.001'))
    UnitDefinition.objects.create(name='Microhenry', symbol='uH', quantity_of_measure=inductance,
                                  base_multiplier=Decimal('0.000001'))
    UnitDefinition.objects.create(name='Nanohenry', symbol='nH', quantity_of_measure=inductance,
                                  base_multiplier=Decimal('0.000000001'))

    # Frequency
    frequency = QuantityOfMeasure.objects.create(name='Frequency')
    UnitDefinition.objects.create(name='Hertz', symbol='Hz', quantity_of_measure=frequency,
                                  base_multiplier=Decimal('1.0'))
    UnitDefinition.objects.create(name='Kilohertz', symbol='kHz', quantity_of_measure=frequency,
                                  base_multiplier=Decimal('1000.0'))
    UnitDefinition.objects.create(name='Megahertz', symbol='MHz', quantity_of_measure=frequency,
                                  base_multiplier=Decimal('1000000.0'))
    UnitDefinition.objects.create(name='Gigahertz', symbol='GHz', quantity_of_measure=frequency,
                                  base_multiplier=Decimal('1000000000.0'))

    # Power
    power = QuantityOfMeasure.objects.create(name='Power')
    UnitDefinition.objects.create(name='Watt', symbol='W', quantity_of_measure=power, base_multiplier=Decimal('1.0'))
    UnitDefinition.objects.create(name='Milliwatt', symbol='mW', quantity_of_measure=power,
                                  base_multiplier=Decimal('0.001'))
    UnitDefinition.objects.create(name='Microwatt', symbol='uW', quantity_of_measure=power,
                                  base_multiplier=Decimal('0.000001'))
    UnitDefinition.objects.create(name='Kilowatt', symbol='kW', quantity_of_measure=power,
                                  base_multiplier=Decimal('1000.0'))
    UnitDefinition.objects.create(name='Megawatt', symbol='MW', quantity_of_measure=power,
                                  base_multiplier=Decimal('1000000.0'))

    # Distance
    distance = QuantityOfMeasure.objects.create(name='Distance')
    UnitDefinition.objects.create(name='Meter', symbol='m', quantity_of_measure=distance,
                                  base_multiplier=Decimal('1.0'))
    UnitDefinition.objects.create(name='Centimeter', symbol='cm', quantity_of_measure=distance,
                                  base_multiplier=Decimal('0.01'))
    UnitDefinition.objects.create(name='Millimeter', symbol='mm', quantity_of_measure=distance,
                                  base_multiplier=Decimal('0.001'))
    UnitDefinition.objects.create(name='Micrometer', symbol='um', quantity_of_measure=distance,
                                  base_multiplier=Decimal('0.000001'))
    UnitDefinition.objects.create(name='Nanometer', symbol='nm', quantity_of_measure=distance,
                                  base_multiplier=Decimal('0.000000001'))
    UnitDefinition.objects.create(name='Kilometer', symbol='km', quantity_of_measure=distance,
                                  base_multiplier=Decimal('1000.0'))
    UnitDefinition.objects.create(name='Inch', symbol='in', quantity_of_measure=distance,
                                  base_multiplier=Decimal('0.0254'))
    UnitDefinition.objects.create(name='Foot', symbol='ft', quantity_of_measure=distance,
                                  base_multiplier=Decimal('0.3048'))
    UnitDefinition.objects.create(name='Yard', symbol='yd', quantity_of_measure=distance,
                                  base_multiplier=Decimal('0.9144'))
    UnitDefinition.objects.create(name='Mil', symbol='mil', quantity_of_measure=distance,
                                  base_multiplier=Decimal('0.0000254'))

    # Weight
    weight = QuantityOfMeasure.objects.create(name='Weight')
    UnitDefinition.objects.create(name='Gram', symbol='g', quantity_of_measure=weight, base_multiplier=Decimal('1.0'))
    UnitDefinition.objects.create(name='Milligram', symbol='mg', quantity_of_measure=weight,
                                  base_multiplier=Decimal('0.001'))
    UnitDefinition.objects.create(name='Kilogram', symbol='kg', quantity_of_measure=weight,
                                  base_multiplier=Decimal('1000.0'))
    UnitDefinition.objects.create(name='Ounce', symbol='oz', quantity_of_measure=weight,
                                  base_multiplier=Decimal('28.3495'))
    UnitDefinition.objects.create(name='Pound', symbol='lb', quantity_of_measure=weight,
                                  base_multiplier=Decimal('453.592'))

    # Temperature
    temperature = QuantityOfMeasure.objects.create(name='Temperature')
    UnitDefinition.objects.create(name='Celsius', symbol='C', quantity_of_measure=temperature,
                                  base_multiplier=Decimal('1.0'))
    UnitDefinition.objects.create(name='Fahrenheit', symbol='F', quantity_of_measure=temperature,
                                  base_multiplier=Decimal('1.0'))

    # Memory
    memory = QuantityOfMeasure.objects.create(name='Memory')
    UnitDefinition.objects.create(name='Byte', symbol='B', quantity_of_measure=memory, base_multiplier=Decimal('1.0'))
    UnitDefinition.objects.create(name='Kilobyte', symbol='KB', quantity_of_measure=memory,
                                  base_multiplier=Decimal('1024.0'))
    UnitDefinition.objects.create(name='Megabyte', symbol='MB', quantity_of_measure=memory,
                                  base_multiplier=Decimal('1048576.0'))
    UnitDefinition.objects.create(name='Gigabyte', symbol='GB', quantity_of_measure=memory,
                                  base_multiplier=Decimal('1073741824.0'))
    UnitDefinition.objects.create(name='Terabyte', symbol='TB', quantity_of_measure=memory,
                                  base_multiplier=Decimal('1099511627776.0'))

    # Dimensionless / Ratio
    dimensionless = QuantityOfMeasure.objects.create(name='Dimensionless')
    UnitDefinition.objects.create(name='Percent', symbol='%', quantity_of_measure=dimensionless,
                                  base_multiplier=Decimal('0.01'))
    UnitDefinition.objects.create(name='Parts per Million', symbol='ppm', quantity_of_measure=dimensionless,
                                  base_multiplier=Decimal('0.000001'))


def remove_unit_definitions(apps, schema_editor):
    """Reverse function to clean up units."""
    QuantityOfMeasure = apps.get_model('bom', 'QuantityOfMeasure')
    UnitDefinition = apps.get_model('bom', 'UnitDefinition')
    UnitDefinition.objects.all().delete()
    QuantityOfMeasure.objects.all().delete()


def get_field_map():
    """
    Shared mapping for forward and reverse.
    NOTE: 'value' is intentionally excluded here as it is handled dynamically.
    """
    return {
        'attribute': ('attribute', 'Attribute', 'string', None),
        'pin_count': ('pin_count', 'Pin Count', 'number', None),
        'tolerance': ('tolerance', 'Tolerance', 'string', 'Dimensionless'),
        'package': ('package', 'Package', 'string', None),
        'material': ('material', 'Material', 'string', None),
        'finish': ('finish', 'Finish', 'string', None),
        'color': ('color', 'Color', 'string', None),
        'length': ('length', 'Length', 'number', 'Distance'),
        'width': ('width', 'Width', 'number', 'Distance'),
        'height': ('height', 'Height', 'number', 'Distance'),
        'weight': ('weight', 'Weight', 'number', 'Weight'),
        'temperature_rating': ('temperature_rating', 'Temperature Rating', 'number', 'Temperature'),
        'temperature_rating_range_max': ('temperature_rating_range_max', 'Temperature Rating Max', 'number',
                                         'Temperature'),
        'temperature_rating_range_min': ('temperature_rating_range_min', 'Temperature Rating Min', 'number',
                                         'Temperature'),
        'wavelength': ('wavelength', 'Wavelength', 'number', 'Distance'),
        'frequency': ('frequency', 'Frequency', 'number', 'Frequency'),
        'memory': ('memory', 'Memory', 'number', 'Memory'),
        'interface': ('interface', 'Interface', 'string', None),
        'power_rating': ('power_rating', 'Power Rating', 'number', 'Power'),
        'supply_voltage': ('supply_voltage', 'Supply Voltage', 'number', 'Voltage'),
        'voltage_rating': ('voltage_rating', 'Voltage Rating', 'number', 'Voltage'),
        'current_rating': ('current_rating', 'Current Rating', 'number', 'Current'),
    }


def migrate_part_revision_data(apps, schema_editor):
    PartRevision = apps.get_model('bom', 'PartRevision')
    PartClass = apps.get_model('bom', 'PartClass')
    PartRevisionPropertyDefinition = apps.get_model('bom', 'PartRevisionPropertyDefinition')
    PartRevisionProperty = apps.get_model('bom', 'PartRevisionProperty')
    UnitDefinition = apps.get_model('bom', 'UnitDefinition')
    QuantityOfMeasure = apps.get_model('bom', 'QuantityOfMeasure')

    field_map = get_field_map()
    definitions = {}

    # 1. Create Standard Property Definitions
    for old_field, (code, name, type_val, quantity_name) in field_map.items():
        qom_obj = None
        if quantity_name:
            qom_obj = QuantityOfMeasure.objects.get(name=quantity_name)

        # Map long type names to single character codes
        type_mapping = {
            'number': 'D',
            'string': 'S',
            'boolean': 'B',
        }
        mapped_type = type_mapping.get(type_val, type_val)

        definition, created = PartRevisionPropertyDefinition.objects.get_or_create(
            code=code,
            defaults={'name': name, 'type': mapped_type, 'quantity_of_measure': qom_obj, 'organization': None}
        )
        definitions[old_field] = definition

    # 2. Create Dynamic PLM Definitions (Resistance, Capacitance, etc)
    # These replace the generic 'value' column
    qom_res = QuantityOfMeasure.objects.get(name='Resistance')
    def_resistance, _ = PartRevisionPropertyDefinition.objects.get_or_create(
        code='resistance',
        defaults={'name': 'Resistance', 'type': 'D', 'quantity_of_measure': qom_res, 'organization': None}
    )

    qom_cap = QuantityOfMeasure.objects.get(name='Capacitance')
    def_capacitance, _ = PartRevisionPropertyDefinition.objects.get_or_create(
        code='capacitance',
        defaults={'name': 'Capacitance', 'type': 'D', 'quantity_of_measure': qom_cap, 'organization': None}
    )

    qom_ind = QuantityOfMeasure.objects.get(name='Inductance')
    def_inductance, _ = PartRevisionPropertyDefinition.objects.get_or_create(
        code='inductance',
        defaults={'name': 'Inductance', 'type': 'D', 'quantity_of_measure': qom_ind, 'organization': None}
    )

    # Fallback for Generic Parts (ICs, etc) that have a 'value' but no specific type
    def_value, _ = PartRevisionPropertyDefinition.objects.get_or_create(
        code='value',
        defaults={'name': 'Value', 'type': 'S', 'quantity_of_measure': None, 'organization': None}
    )

    # 3. Helper for Unit Lookup
    unit_cache = {}

    def get_unit(symbol):
        if not symbol: return None
        clean_symbol = symbol.strip().lower()
        symbol_map = {
            'ohm': 'Ω', 'ohms': 'Ω', 'kohm': 'kΩ', 'kohms': 'kΩ', 'mohm': 'MΩ', 'mohms': 'MΩ',
            'Ω': 'Ω', 'kΩ': 'kΩ', 'mΩ': 'mΩ', 'MΩ': 'MΩ',
            'f': 'F', 'farad': 'F', 'farads': 'F', 'mf': 'mF', 'uf': 'uF', 'nf': 'nF', 'pf': 'pF',
            'microfarad': 'uF', 'µf': 'uF',
            'v': 'V', 'volt': 'V', 'volts': 'V', 'mv': 'mV', 'uv': 'uV', 'kv': 'kV', 'µv': 'uV',
            'a': 'A', 'amp': 'A', 'amps': 'A', 'ampere': 'A', 'ma': 'mA', 'ua': 'uA', 'ka': 'kA', 'µa': 'uA',
            'h': 'H', 'henry': 'H', 'henries': 'H', 'mh': 'mH', 'uh': 'uH', 'nh': 'nH', 'µh': 'uH',
            'hz': 'Hz', 'khz': 'kHz', 'mhz': 'MHz', 'ghz': 'GHz',
            'w': 'W', 'mw': 'mW', 'uw': 'uW', 'kw': 'kW', 'mw': 'MW',
            'm': 'm', 'mm': 'mm', 'cm': 'cm', 'km': 'km', 'g': 'g', 'kg': 'kg', 'mg': 'mg',
            's': 's', 'ms': 'ms', 'us': 'us', 'ns': 'ns',
            'c': 'C', 'degc': 'C', '°c': 'C', 'f': 'F', 'degf': 'F', '°f': 'F',
            'ppm': 'ppm', '%': '%', 'percent': '%'
        }
        mapped_symbol = symbol_map.get(clean_symbol, symbol.strip())
        if mapped_symbol in unit_cache: return unit_cache[mapped_symbol]
        try:
            unit = UnitDefinition.objects.filter(symbol=mapped_symbol).first()
            if unit:
                unit_cache[mapped_symbol] = unit
                return unit
            return None
        except Exception:
            return None

    # 4. Batch Process Data
    class_def_map = defaultdict(set)
    batch_properties = []
    BATCH_SIZE = 2000

    for pr in PartRevision.objects.select_related('part', 'part__number_class').iterator():
        part_class_id = getattr(pr.part, 'number_class_id', None)
        part_class_name = getattr(pr.part.number_class, 'name', '').lower() if pr.part.number_class else ''

        # --- A. HANDLE LEGACY 'VALUE' COLUMN INTELLIGENTLY ---
        val = getattr(pr, 'value', None)
        if val is not None and val != '':
            # Decide which Definition to use based on Class
            target_def = def_value  # Default fallback
            target_unit_name = None  # For inference

            if 'resistor' in part_class_name:
                target_def = def_resistance
                target_unit_name = 'Ω'  # Infer Ohms if missing
            elif 'capacitor' in part_class_name:
                target_def = def_capacitance
                target_unit_name = 'F'  # Infer Farads if missing
            elif 'inductor' in part_class_name or 'ferrite' in part_class_name:
                target_def = def_inductance
                target_unit_name = 'H'

            if part_class_id:
                class_def_map[part_class_id].add(target_def.id)

            # Check for existing unit in legacy column
            legacy_unit = getattr(pr, 'value_units', None)

            # If legacy unit is missing, use our inferred one (e.g. Ohms for Resistors)
            unit_ref = get_unit(legacy_unit) if legacy_unit else get_unit(target_unit_name)

            prop = PartRevisionProperty(
                part_revision=pr,
                property_definition=target_def,
                value_raw=str(val),
                unit_definition=unit_ref
            )

            # Normalize
            if unit_ref and val:
                try:
                    clean_val = str(val).lower().replace('k', '').replace('m', '').replace('u', '')
                    val_dec = Decimal(clean_val)
                    mult_dec = Decimal(unit_ref.base_multiplier)
                    prop.value_normalized = val_dec * mult_dec
                except (ValueError, TypeError, Exception):
                    pass

            batch_properties.append(prop)

        # --- B. HANDLE STANDARD COLUMNS ---
        for old_field, definition in definitions.items():
            val = getattr(pr, old_field, None)

            if val is not None and val != '':
                if part_class_id:
                    class_def_map[part_class_id].add(definition.id)

                unit_field = old_field + '_units'
                unit_val = getattr(pr, unit_field, None)

                # Intelligent Inference for Tolerance
                if old_field == 'tolerance':
                    str_val = str(val).lower()
                    if 'ppm' in str_val:
                        unit_val = 'ppm'
                        val = str_val.replace('ppm', '').strip()
                    elif '%' in str_val:
                        unit_val = '%'
                        val = str_val.replace('%', '').strip()
                    else:
                        if not any(x in str_val for x in ['f', 'v', 'h']):
                            unit_val = '%'

                unit_ref = get_unit(unit_val)

                prop = PartRevisionProperty(
                    part_revision=pr,
                    property_definition=definition,
                    value_raw=str(val),
                    unit_definition=unit_ref
                )

                if unit_ref and val:
                    try:
                        clean_val = str(val).lower().replace('k', '').replace('m', '').replace('u', '')
                        val_dec = Decimal(clean_val)
                        mult_dec = Decimal(unit_ref.base_multiplier)
                        prop.value_normalized = val_dec * mult_dec
                    except (ValueError, TypeError, Exception):
                        pass

                batch_properties.append(prop)

                if len(batch_properties) >= BATCH_SIZE:
                    PartRevisionProperty.objects.bulk_create(batch_properties)
                    batch_properties = []

    if batch_properties:
        PartRevisionProperty.objects.bulk_create(batch_properties)

    for class_id, def_ids in class_def_map.items():
        try:
            pc = PartClass.objects.get(id=class_id)
            pc.property_definitions.add(*def_ids)
        except PartClass.DoesNotExist:
            continue


def reverse_migrate_part_revision_data(apps, schema_editor):
    """Restores data from PartRevisionProperties back to PartRevision columns."""
    PartRevision = apps.get_model('bom', 'PartRevision')
    PartRevisionProperty = apps.get_model('bom', 'PartRevisionProperty')

    # Reverse Map: Property Name -> (Old Field Name, Old Unit Field Name)
    field_map = get_field_map()
    prop_name_to_field = {}
    for old_field, (code, name, _, _) in field_map.items():
        unit_field = old_field + '_units'
        prop_name_to_field[name] = (old_field, unit_field)

    # ADD DYNAMIC MAPPINGS FOR REVERSE
    # Map the new PLM fields back to the old 'value' column so data is not lost on reverse
    prop_name_to_field['Value'] = ('value', 'value_units')
    prop_name_to_field['Resistance'] = ('value', 'value_units')
    prop_name_to_field['Capacitance'] = ('value', 'value_units')
    prop_name_to_field['Inductance'] = ('value', 'value_units')

    batch_update_list = []
    BATCH_SIZE = 2000
    fields_to_update = set()

    # Iterate Revisions
    # Prefetch properties to avoid N+1
    qs = PartRevision.objects.prefetch_related('properties', 'properties__property_definition',
                                               'properties__unit_definition')

    for pr in qs.iterator():
        updated = False
        for prop in pr.properties.all():
            prop_name = prop.property_definition.name
            if prop_name in prop_name_to_field:
                col_name, unit_col_name = prop_name_to_field[prop_name]

                # Restore Value
                if prop.value_raw:
                    setattr(pr, col_name, prop.value_raw)
                    fields_to_update.add(col_name)
                    updated = True

                # Restore Unit
                if prop.unit_definition and hasattr(pr, unit_col_name):
                    setattr(pr, unit_col_name, prop.unit_definition.symbol)
                    fields_to_update.add(unit_col_name)
                    updated = True

        if updated:
            batch_update_list.append(pr)

        if len(batch_update_list) >= BATCH_SIZE:
            PartRevision.objects.bulk_update(batch_update_list, list(fields_to_update))
            batch_update_list = []

    if batch_update_list and fields_to_update:
        PartRevision.objects.bulk_update(batch_update_list, list(fields_to_update))

class Migration(migrations.Migration):
    dependencies = [
        ('bom', '0051_alter_manufacturer_organization_and_more'),
    ]

    operations = [
        migrations.CreateModel(
            name='PartRevisionPropertyDefinition',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('code', models.CharField(blank=True, max_length=64)),
                ('name', models.CharField(max_length=64)),
                ('type', models.CharField(choices=[('S', 'String'), ('D', 'Number'), ('B', 'Boolean')], max_length=1)),
                ('required', models.BooleanField(default=False)),
                ('organization',
                 models.ForeignKey(blank=True, help_text='Leave empty for a Global/System record.', null=True,
                                   on_delete=django.db.models.deletion.CASCADE, to=settings.BOM_ORGANIZATION_MODEL)),
            ],
        ),
        migrations.AddField(
            model_name='partclass',
            name='property_definitions',
            field=models.ManyToManyField(blank=True, related_name='part_classes',
                                         to='bom.partrevisionpropertydefinition'),
        ),
        migrations.CreateModel(
            name='QuantityOfMeasure',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(help_text='e.g. Voltage', max_length=64)),
                ('organization',
                 models.ForeignKey(blank=True, help_text='Leave empty for a Global/System record.', null=True,
                                   on_delete=django.db.models.deletion.CASCADE, to=settings.BOM_ORGANIZATION_MODEL)),
            ],
            options={
                'unique_together': {('organization', 'name')},
            },
        ),
        migrations.AddField(
            model_name='partrevisionpropertydefinition',
            name='quantity_of_measure',
            field=models.ForeignKey(blank=True,
                                    null=True, on_delete=django.db.models.deletion.SET_NULL,
                                    to='bom.quantityofmeasure'),
        ),
        migrations.CreateModel(
            name='UnitDefinition',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=64)),
                ('symbol', models.CharField(max_length=16)),
                ('base_multiplier', models.DecimalField(decimal_places=20, default=Decimal('1.0'), max_digits=40)),
                ('organization',
                 models.ForeignKey(blank=True, help_text='Leave empty for a Global/System record.', null=True,
                                   on_delete=django.db.models.deletion.CASCADE, to=settings.BOM_ORGANIZATION_MODEL)),
                ('quantity_of_measure',
                 models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='units',
                                   to='bom.quantityofmeasure')),
            ],
            options={
                'ordering': ['base_multiplier'],
                'unique_together': {('organization', 'quantity_of_measure', 'symbol')},
            },
        ),
        migrations.CreateModel(
            name='PartRevisionProperty',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('value_raw', models.CharField(max_length=255)),
                ('value_normalized', models.DecimalField(blank=True, decimal_places=20, max_digits=40, null=True)),
                ('part_revision',
                 models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='properties',
                                   to='bom.partrevision')),
                ('property_definition', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
                                                          to='bom.partrevisionpropertydefinition')),
                ('unit_definition',
                 models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL,
                                   to='bom.unitdefinition')),
            ],
        ),
        migrations.AlterUniqueTogether(
            name='partrevisionpropertydefinition',
            unique_together={('organization', 'code')},
        ),

        migrations.RunPython(create_unit_definitions, remove_unit_definitions),
        migrations.RunPython(migrate_part_revision_data, reverse_migrate_part_revision_data),

        migrations.RemoveField(model_name='partrevision', name='attribute'),
        migrations.RemoveField(model_name='partrevision', name='color'),
        migrations.RemoveField(model_name='partrevision', name='current_rating'),
        migrations.RemoveField(model_name='partrevision', name='current_rating_units'),
        migrations.RemoveField(model_name='partrevision', name='finish'),
        migrations.RemoveField(model_name='partrevision', name='frequency'),
        migrations.RemoveField(model_name='partrevision', name='frequency_units'),
        migrations.RemoveField(model_name='partrevision', name='height'),
        migrations.RemoveField(model_name='partrevision', name='height_units'),
        migrations.RemoveField(model_name='partrevision', name='interface'),
        migrations.RemoveField(model_name='partrevision', name='length'),
        migrations.RemoveField(model_name='partrevision', name='length_units'),
        migrations.RemoveField(model_name='partrevision', name='material'),
        migrations.RemoveField(model_name='partrevision', name='memory'),
        migrations.RemoveField(model_name='partrevision', name='memory_units'),
        migrations.RemoveField(model_name='partrevision', name='package'),
        migrations.RemoveField(model_name='partrevision', name='pin_count'),
        migrations.RemoveField(model_name='partrevision', name='power_rating'),
        migrations.RemoveField(model_name='partrevision', name='power_rating_units'),
        migrations.RemoveField(model_name='partrevision', name='supply_voltage'),
        migrations.RemoveField(model_name='partrevision', name='supply_voltage_units'),
        migrations.RemoveField(model_name='partrevision', name='temperature_rating'),
        migrations.RemoveField(model_name='partrevision', name='temperature_rating_range_max'),
        migrations.RemoveField(model_name='partrevision', name='temperature_rating_range_min'),
        migrations.RemoveField(model_name='partrevision', name='temperature_rating_units'),
        migrations.RemoveField(model_name='partrevision', name='tolerance'),
        migrations.RemoveField(model_name='partrevision', name='value'),
        migrations.RemoveField(model_name='partrevision', name='value_units'),
        migrations.RemoveField(model_name='partrevision', name='voltage_rating'),
        migrations.RemoveField(model_name='partrevision', name='voltage_rating_units'),
        migrations.RemoveField(model_name='partrevision', name='wavelength'),
        migrations.RemoveField(model_name='partrevision', name='wavelength_units'),
        migrations.RemoveField(model_name='partrevision', name='weight'),
        migrations.RemoveField(model_name='partrevision', name='weight_units'),
        migrations.RemoveField(model_name='partrevision', name='width'),
        migrations.RemoveField(model_name='partrevision', name='width_units'),
    ]
