diff --git a/docs/usage/import_export.md b/docs/usage/import_export.md index f4d8d91cc..9f1525c2f 100644 --- a/docs/usage/import_export.md +++ b/docs/usage/import_export.md @@ -109,6 +109,21 @@ supplier is not specified, the price and supplier product number fields will be * **`supplier_product_number`** or **`supplier_part_number`** or * **`spn`**: The supplier product number of the part. * **`price`**: The price of the part in the base currency of the database (by default euro). +The following fields set the EDA / KiCad metadata of the part (see [EDA / KiCad integration](eda_integration.md)). +These can be given either as the flat column names below, or in the nested `eda_info.*` form used by the +CSV/JSON export and the [example file](#example-data) (e.g. `eda_info.kicad_symbol`), so a file exported from +Part-DB can be re-imported without renaming its headers: + +* **`eda_kicad_symbol`** or **`kicad_symbol`**: The KiCad symbol of the part, e.g. `Device:R`. +* **`eda_kicad_footprint`** or **`kicad_footprint`**: The KiCad footprint, e.g. `Resistor_SMD:R_0805_2012Metric`. +* **`eda_reference_prefix`** or **`kicad_reference`**: The schematic reference prefix, e.g. `R`, `C`, `L`. +* **`eda_value`** or **`kicad_value`**: The value shown in the EDA tool, e.g. `10k`. +* **`eda_exclude_from_bom`** (or **`eda_exclude_bom`**), **`eda_exclude_from_board`** (or **`eda_exclude_board`**), + **`eda_exclude_from_sim`** (or **`eda_exclude_sim`**): Booleans (`1`/`0`) to exclude the part from the BOM, board + or simulation. +* **`eda_visibility`**: Boolean (`1`/`0`) controlling whether the part is exposed to the EDA tool. The inverse + convenience alias **`eda_invisible`** is also accepted (so `eda_invisible=1` hides the part). + #### Example data Here you can find some example data for the import of parts, you can use it as a template for your own import ( diff --git a/src/Serializer/PartNormalizer.php b/src/Serializer/PartNormalizer.php index 8486a634a..50f761324 100644 --- a/src/Serializer/PartNormalizer.php +++ b/src/Serializer/PartNormalizer.php @@ -63,7 +63,9 @@ class PartNormalizer implements NormalizerInterface, DenormalizerInterface, Norm 'eda_exclude_bom' => 'eda_exclude_from_bom', 'eda_exclude_board' => 'eda_exclude_from_board', 'eda_exclude_sim' => 'eda_exclude_from_sim', - 'eda_invisible' => 'eda_visibility', + //NOTE: "eda_invisible" is intentionally NOT mapped here: it is the *inverse* of + //"eda_visibility", so a plain key rename would store the wrong value. It is handled + //(and inverted) explicitly in applyEdaFields(). ]; public function __construct( @@ -235,6 +237,9 @@ private function applyEdaFields(Part $part, array $data): void } if (isset($data['eda_visibility']) && $data['eda_visibility'] !== '') { $edaInfo->setVisibility(filter_var($data['eda_visibility'], FILTER_VALIDATE_BOOLEAN)); + } elseif (isset($data['eda_invisible']) && $data['eda_invisible'] !== '') { + //"eda_invisible" is the inverse convenience alias of "eda_visibility" + $edaInfo->setVisibility(!filter_var($data['eda_invisible'], FILTER_VALIDATE_BOOLEAN)); } } diff --git a/tests/Services/ImportExportSystem/EntityImporterTest.php b/tests/Services/ImportExportSystem/EntityImporterTest.php index b0044dda6..29804dc6d 100644 --- a/tests/Services/ImportExportSystem/EntityImporterTest.php +++ b/tests/Services/ImportExportSystem/EntityImporterTest.php @@ -350,6 +350,84 @@ public function testImportStringParts(): void $this->assertSame('test,test2', $results[0]->getTags()); } + public function testImportAcceptsNestedEdaInfoColumns(): void + { + //The API / JSON export writes EDA columns as "eda_info.kicad_symbol"; re-importing such a + //file must fill the EDA fields (previously these columns were silently dropped). + $input = "name;eda_info.kicad_symbol;eda_info.kicad_footprint;eda_info.reference_prefix;eda_info.value\n" + ."Nested EDA part;Device:L;Inductor_THT:L_Axial_0307;L;100uH"; + + $category = new Category(); + $category->setName('Test EDA category'); + + $errors = []; + $results = $this->service->importString($input, [ + 'class' => Part::class, + 'format' => 'csv', + 'csv_delimiter' => ';', + 'create_unknown_datastructures' => true, + 'part_category' => $category, + ], $errors); + + $this->assertCount(1, $results); + $this->assertEmpty($errors); + $eda = $results[0]->getEdaInfo(); + $this->assertSame('Device:L', $eda->getKicadSymbol()); + $this->assertSame('Inductor_THT:L_Axial_0307', $eda->getKicadFootprint()); + $this->assertSame('L', $eda->getReferencePrefix()); + $this->assertSame('100uH', $eda->getValue()); + } + + public function testImportAcceptsFlatEdaColumns(): void + { + //The documented flat form (and its short aliases) must keep working. + $input = "name;eda_kicad_symbol;kicad_footprint;kicad_reference\n" + ."Flat EDA part;Device:R;Resistor_SMD:R_0805_2012Metric;R"; + + $category = new Category(); + $category->setName('Test EDA category'); + + $errors = []; + $results = $this->service->importString($input, [ + 'class' => Part::class, + 'format' => 'csv', + 'csv_delimiter' => ';', + 'create_unknown_datastructures' => true, + 'part_category' => $category, + ], $errors); + + $this->assertCount(1, $results); + $this->assertEmpty($errors); + $eda = $results[0]->getEdaInfo(); + $this->assertSame('Device:R', $eda->getKicadSymbol()); + $this->assertSame('Resistor_SMD:R_0805_2012Metric', $eda->getKicadFootprint()); + $this->assertSame('R', $eda->getReferencePrefix()); + } + + public function testImportInvisibleAliasInvertsVisibility(): void + { + //"eda_invisible" is the inverse convenience alias of "eda_visibility": eda_invisible=1 + //must make the part NOT visible to the EDA tool (visibility=false), not visible. + $input = "name;eda_invisible\n" + ."Hidden EDA part;1"; + + $category = new Category(); + $category->setName('Test EDA category'); + + $errors = []; + $results = $this->service->importString($input, [ + 'class' => Part::class, + 'format' => 'csv', + 'csv_delimiter' => ';', + 'create_unknown_datastructures' => true, + 'part_category' => $category, + ], $errors); + + $this->assertCount(1, $results); + $this->assertEmpty($errors); + $this->assertFalse($results[0]->getEdaInfo()->getVisibility()); + } + public function testImportExcelFileProjects(): void { $spreadsheet = new Spreadsheet();