diff --git a/.env b/.env
index f23afe8b..73b7b350 100644
--- a/.env
+++ b/.env
@@ -50,8 +50,6 @@ EMAIL_SENDER_EMAIL=noreply@partdb.changeme
EMAIL_SENDER_NAME="Part-DB Mailer"
# Set this to 1 to allow reset of a password per email
ALLOW_EMAIL_PW_RESET=0
-# Set this to 0 to allow to enter already available IPN. In this case a unique increment is appended to the user input.
-ENFORCE_UNIQUE_IPN=1
###################################################################################
# Error pages settings
@@ -62,17 +60,6 @@ ERROR_PAGE_ADMIN_EMAIL=''
# If this is set to true, solutions to common problems are shown on error pages. Disable this, if you do not want your users to see them...
ERROR_PAGE_SHOW_HELP=1
-##################################################################################
-# Part table settings
-##################################################################################
-
-# Configure which columns will be visible by default in the specific table (and in which order).
-# This is a comma separated list of column names. See documentation for available values.
-TABLE_PARTS_DEFAULT_COLUMNS=name,description,category,footprint,manufacturer,storage_location,amount
-TABLE_ASSEMBLIES_DEFAULT_COLUMNS=id,ipn,name,description,referencedAssemblies,edit
-TABLE_ASSEMBLIES_BOM_DEFAULT_COLUMNS=quantity,id,ipn,name,description
-
-
###################################################################################
# SAML Single sign on-settings
###################################################################################
@@ -125,22 +112,6 @@ NO_URL_REWRITE_AVAILABLE=0
# Set to 1, if Part-DB should redirect all HTTP requests to HTTPS. You dont need to configure this, if your webserver already does this.
REDIRECT_TO_HTTPS=0
-# If you want to use fixer.io for currency conversion, you have to set this to your API key
-FIXER_API_KEY=CHANGEME
-
-# Override value if you want to show to show a given text on homepage.
-# When this is empty the content of config/banner.md is used as banner
-BANNER=""
-
-# Enable the part image overlay which shows name and filename of the picture
-SHOW_PART_IMAGE_OVERLAY=1
-
-# Define the number of digits used for the incremental numbering of parts in the IPN (Internal Part Number) autocomplete system.
-AUTOCOMPLETE_PART_DIGITS=4
-
-APP_ENV=prod
-APP_SECRET=a03498528f5a5fc089273ec9ae5b2849
-
# Set this to zero, if you want to disable the year 2038 bug check on 32-bit systems (it will cause errors with current 32-bit PHP versions)
DISABLE_YEAR2038_BUG_CHECK=0
diff --git a/config/parameters.yaml b/config/parameters.yaml
index d225a52e..3931729d 100644
--- a/config/parameters.yaml
+++ b/config/parameters.yaml
@@ -9,8 +9,6 @@ parameters:
# This is used as workaround for places where we can not access the settings directly (like the 2FA application names)
partdb.title: '%env(string:settings:customization:instanceName)%' # The title shown inside of Part-DB (e.g. in the navbar and on homepage)
partdb.locale_menu: ['en', 'de', 'it', 'fr', 'ru', 'ja', 'cs', 'da', 'zh', 'pl'] # The languages that are shown in user drop down menu
- partdb.enforce_change_comments_for: '%env(csv:ENFORCE_CHANGE_COMMENTS_FOR)%' # The actions for which a change comment is required (e.g. "part_edit", "part_create", etc.). If this is empty, change comments are not required at all.
- partdb.autocomplete_part_digits: '%env(trim:string:AUTOCOMPLETE_PART_DIGITS)%' # The number of digits used for the incremental numbering of parts in the IPN (Internal Part Number) autocomplete system.
partdb.default_uri: '%env(string:DEFAULT_URI)%' # The default URI to use for the Part-DB instance (e.g. https://part-db.example.com/). This is used for generating links in emails
@@ -18,26 +16,11 @@ parameters:
partdb.create_assembly_use_ipn_placeholder_in_name: '%env(bool:CREATE_ASSEMBLY_USE_IPN_PLACEHOLDER_IN_NAME)%' # Use an %%ipn%% placeholder in the name of an assembly. Placeholder is replaced with the ipn input while saving.
- partdb.data_sources.synonyms: # Define your own synonyms for the given data sources
- # Possible datasources: category, storagelocation, footprint, manufacturer, supplier, project, assembly
- # Possible locales like the ones in 'partdb.locale_menu': en, de, it, fr, ru, ja, cs, da, zh, pl
- #category:
- #de: 'Bauteil Kategorien'
- #en: 'Part categories'
- #project:
- #de: 'Geräte'
- #en: 'Devices'
- #assembly:
- #de: 'Zusammengestellte Baugruppe'
- #en: 'Combined assembly'
-
-
######################################################################################################################
# Users and Privacy
######################################################################################################################
partdb.gdpr_compliance: true # If this option is activated, IP addresses are anonymized to be GDPR compliant
partdb.users.email_pw_reset: '%env(bool:ALLOW_EMAIL_PW_RESET)%' # Config if users are able, to reset their password by email. By default this enabled, when a mail server is configured.
- partdb.users.enforce_unique_ipn: '%env(bool:ENFORCE_UNIQUE_IPN)%' # Config if users are able, to enter an already available IPN. In this case a unique increment is appended to the user input.
######################################################################################################################
# Mail settings
@@ -62,12 +45,6 @@ parameters:
######################################################################################################################
partdb.saml.enabled: '%env(bool:SAML_ENABLED)%' # If this is set to true, SAML authentication is enabled
- ######################################################################################################################
- # Table settings
- ######################################################################################################################
- partdb.table.assemblies.default_columns: '%env(trim:string:TABLE_ASSEMBLIES_DEFAULT_COLUMNS)%' # The default columns in assembly tables and their order
- partdb.table.assemblies_bom.default_columns: '%env(trim:string:TABLE_ASSEMBLIES_BOM_DEFAULT_COLUMNS)%' # The default columns in assembly bom tables and their order
-
######################################################################################################################
# Miscellaneous
######################################################################################################################
diff --git a/docs/configuration.md b/docs/configuration.md
index ea02b227..d04f1a3a 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -148,7 +148,7 @@ bundled with Part-DB. Set `DATABASE_MYSQL_SSL_VERIFY_CERT` if you want to accept
are: `name`, `id`, `ipn`, `description`, `referencedAssemblies`, `edit`, `addedDate`, `lastModified`.
* `TABLE_ASSEMBLIES_BOM_DEFAULT_COLUMNS`: The columns in assemblies bom tables, which are visible by default (when loading table for first time).
Also specify the default order of the columns. This is a comma separated list of column names. Available columns
- are: `quantity`, `name`, `id`, `ipn`, `description`, `addedDate`, `lastModified`.
+ are: `quantity`, `name`, `id`, `ipn`, `description`, `category`, `footprint`, `manufacturer`, `designator`, `mountnames`, `storage_location`, `amount`, `addedDate`, `lastModified`.
* `CREATE_ASSEMBLY_USE_IPN_PLACEHOLDER_IN_NAME`: Use an %%ipn%% placeholder in the name of a assembly. Placeholder is replaced with the ipn input while saving.
### History/Eventlog-related settings
diff --git a/migrations/Version20250304081039.php b/migrations/Version20250304081039.php
index 2c04dfb0..0c64e250 100644
--- a/migrations/Version20250304081039.php
+++ b/migrations/Version20250304081039.php
@@ -145,7 +145,6 @@ final class Version20250304081039 extends AbstractMultiPlatformMigration
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
id_assembly INTEGER DEFAULT NULL,
id_part INTEGER DEFAULT NULL,
- id_project INTEGER DEFAULT NULL,
id_referenced_assembly INTEGER DEFAULT NULL,
price_currency_id INTEGER DEFAULT NULL,
quantity DOUBLE PRECISION NOT NULL,
@@ -157,7 +156,6 @@ final class Version20250304081039 extends AbstractMultiPlatformMigration
datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
CONSTRAINT FK_8C74887E4AD2039E FOREIGN KEY (id_assembly) REFERENCES assemblies (id) NOT DEFERRABLE INITIALLY IMMEDIATE,
CONSTRAINT FK_8C74887EC22F6CC4 FOREIGN KEY (id_part) REFERENCES "parts" (id) NOT DEFERRABLE INITIALLY IMMEDIATE,
- CONSTRAINT FK_8C74887EF12E799E FOREIGN KEY (id_project) REFERENCES projects (id) NOT DEFERRABLE INITIALLY IMMEDIATE,
CONSTRAINT FK_8C74887E22522999 FOREIGN KEY (id_referenced_assembly) REFERENCES assemblies (id) ON UPDATE NO ACTION ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE,
CONSTRAINT FK_8C74887E3FFDCD60 FOREIGN KEY (price_currency_id) REFERENCES currencies (id) NOT DEFERRABLE INITIALLY IMMEDIATE
)
@@ -168,9 +166,6 @@ final class Version20250304081039 extends AbstractMultiPlatformMigration
$this->addSql(<<<'SQL'
CREATE INDEX IDX_8C74887EC22F6CC4 ON assembly_bom_entries (id_part)
SQL);
- $this->addSql(<<<'SQL'
- CREATE INDEX IDX_8C74887EF12E799E ON assembly_bom_entries (id_project)
- SQL);
$this->addSql(<<<'SQL'
CREATE INDEX IDX_8C74887E22522999 ON assembly_bom_entries (id_referenced_assembly)
SQL);
@@ -220,7 +215,6 @@ final class Version20250304081039 extends AbstractMultiPlatformMigration
id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL,
id_assembly INT DEFAULT NULL,
id_part INT DEFAULT NULL,
- id_project INT DEFAULT NULL,
quantity DOUBLE PRECISION NOT NULL,
mountnames TEXT NOT NULL,
name VARCHAR(255) DEFAULT NULL,
@@ -238,9 +232,6 @@ final class Version20250304081039 extends AbstractMultiPlatformMigration
$this->addSql(<<<'SQL'
CREATE INDEX IDX_8C74887EC22F6CC4 ON assembly_bom_entries (id_part)
SQL);
- $this->addSql(<<<'SQL'
- CREATE INDEX IDX_8C74887EF12E799E ON assembly_bom_entries (id_project)
- SQL);
$this->addSql(<<<'SQL'
CREATE INDEX IDX_8C74887E3FFDCD60 ON assembly_bom_entries (price_currency_id)
SQL);
@@ -256,9 +247,6 @@ final class Version20250304081039 extends AbstractMultiPlatformMigration
$this->addSql(<<<'SQL'
ALTER TABLE assembly_bom_entries ADD CONSTRAINT FK_8C74887EC22F6CC4 FOREIGN KEY (id_part) REFERENCES "parts" (id) NOT DEFERRABLE INITIALLY IMMEDIATE
SQL);
- $this->addSql(<<<'SQL'
- ALTER TABLE assembly_bom_entries ADD CONSTRAINT FK_8C74887EF12E799E FOREIGN KEY (id_project) REFERENCES "projects" (id) NOT DEFERRABLE INITIALLY IMMEDIATE
- SQL);
$this->addSql(<<<'SQL'
ALTER TABLE assembly_bom_entries ADD CONSTRAINT FK_8C74887E3FFDCD60 FOREIGN KEY (price_currency_id) REFERENCES currencies (id) NOT DEFERRABLE INITIALLY IMMEDIATE
SQL);
diff --git a/migrations/Version20250929140755.php b/migrations/Version20250929140755.php
new file mode 100644
index 00000000..a45dd8fb
--- /dev/null
+++ b/migrations/Version20250929140755.php
@@ -0,0 +1,26 @@
+addSql('ALTER TABLE assembly_bom_entries ADD designator LONGTEXT NOT NULL AFTER mountnames');
+ }
+
+ public function down(Schema $schema): void
+ {
+ $this->addSql('ALTER TABLE assembly_bom_entries DROP designator');
+ }
+}
diff --git a/src/Controller/PartController.php b/src/Controller/PartController.php
index 29abfad8..69e9557e 100644
--- a/src/Controller/PartController.php
+++ b/src/Controller/PartController.php
@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace App\Controller;
use App\DataTables\LogDataTable;
+use App\Entity\AssemblySystem\Assembly;
use App\Entity\Attachments\AttachmentUpload;
use App\Entity\Parts\Category;
use App\Entity\Parts\Footprint;
diff --git a/src/Controller/ProjectController.php b/src/Controller/ProjectController.php
index 151bf18f..e510506f 100644
--- a/src/Controller/ProjectController.php
+++ b/src/Controller/ProjectController.php
@@ -194,14 +194,14 @@ class ProjectController extends AbstractController
// For PCB imports, proceed directly
$importerResult = $BOMImporter->importFileIntoProject($form->get('file')->getData(), $project, [
- 'type' => $form->get('type')->getData(),
+ 'type' => $import_type,
]);
// Validate the project entries
$errors = $validator->validateProperty($project, 'bom_entries');
- //If no validation errors occured, save the changes and redirect to edit page
- if (count ($errors) === 0 && $importerResult->getViolations()->count() === 0) {
+ //If no validation errors occurred, save the changes and redirect to edit page
+ if (count($errors) === 0 && $importerResult->getViolations()->count() === 0) {
$entries = $importerResult->getBomEntries();
$this->addFlash('success', t('project.bom_import.flash.success', ['%count%' => count($entries)]));
diff --git a/src/DataTables/AssemblyBomEntriesDataTable.php b/src/DataTables/AssemblyBomEntriesDataTable.php
index 93e1566d..55a47584 100644
--- a/src/DataTables/AssemblyBomEntriesDataTable.php
+++ b/src/DataTables/AssemblyBomEntriesDataTable.php
@@ -162,6 +162,12 @@ class AssemblyBomEntriesDataTable implements DataTableTypeInterface
return $html;
},
])
+ ->add('designator', TextColumn::class, [
+ 'label' => 'assembly.bom.designator',
+ 'render' => function ($value, AssemblyBOMEntry $context) {
+ return htmlspecialchars($context->getDesignator());
+ },
+ ])
->add('instockAmount', TextColumn::class, [
'label' => 'assembly.bom.instockAmount',
'visible' => false,
@@ -195,7 +201,7 @@ class AssemblyBomEntriesDataTable implements DataTableTypeInterface
$this->csh->applyVisibilityAndConfigureColumns($dataTable, $this->tableSettings->assembliesBomDefaultColumns,
"TABLE_ASSEMBLIES_BOM_DEFAULT_COLUMNS");
- $dataTable->addOrderBy('name', DataTable::SORT_ASCENDING);
+ $dataTable->addOrderBy('name');
$dataTable->createAdapter(ORMAdapter::class, [
'entity' => Attachment::class,
diff --git a/src/DataTables/PartsDataTable.php b/src/DataTables/PartsDataTable.php
index 716a892d..fd798620 100644
--- a/src/DataTables/PartsDataTable.php
+++ b/src/DataTables/PartsDataTable.php
@@ -282,34 +282,6 @@ final class PartsDataTable implements DataTableTypeInterface
]);
}
- //Add a assembly column to list where the part is used, when the user has the permission to see the assemblies
- if ($this->security->isGranted('read', Assembly::class)) {
- $this->csh->add('assemblies', TextColumn::class, [
- 'label' => $this->translator->trans('assembly.labelp'),
- 'render' => function ($value, Part $context): string {
- //Only show the first 5 assembly names
- $assemblies = $context->getAssemblies();
- $tmp = "";
-
- $max = 5;
-
- for ($i = 0; $i < min($max, count($assemblies)); $i++) {
- $url = $this->urlGenerator->infoURL($assemblies[$i]);
- $tmp .= sprintf('%s', $url, htmlspecialchars($assemblies[$i]->getName()));
- if ($i < count($assemblies) - 1) {
- $tmp .= ", ";
- }
- }
-
- if (count($assemblies) > $max) {
- $tmp .= ", + ".(count($assemblies) - $max);
- }
-
- return $tmp;
- }
- ]);
- }
-
$this->csh
->add('edit', IconLinkColumn::class, [
'label' => $this->translator->trans('part.table.edit'),
diff --git a/src/Entity/AssemblySystem/AssemblyBOMEntry.php b/src/Entity/AssemblySystem/AssemblyBOMEntry.php
index 80b7d6bb..e4337446 100644
--- a/src/Entity/AssemblySystem/AssemblyBOMEntry.php
+++ b/src/Entity/AssemblySystem/AssemblyBOMEntry.php
@@ -36,8 +36,6 @@ use ApiPlatform\OpenApi\Model\Operation;
use ApiPlatform\Serializer\Filter\PropertyFilter;
use App\ApiPlatform\Filter\LikeFilter;
use App\Entity\Contracts\TimeStampableInterface;
-use App\Entity\ProjectSystem\Project;
-use App\Entity\AssemblySystem\Assembly;
use App\Repository\DBElementRepository;
use App\Validator\Constraints\AssemblySystem\AssemblyCycle;
use App\Validator\Constraints\AssemblySystem\AssemblyInvalidBomEntry;
@@ -86,7 +84,7 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
normalizationContext: ['groups' => ['bom_entry:read', 'api:basic:read'], 'openapi_definition_name' => 'Read']
)]
#[ApiFilter(PropertyFilter::class)]
-#[ApiFilter(LikeFilter::class, properties: ["name", "comment", 'mountnames'])]
+#[ApiFilter(LikeFilter::class, properties: ["name", 'mountnames', 'designator', "comment"])]
#[ApiFilter(RangeFilter::class, properties: ['quantity'])]
#[ApiFilter(OrderFilter::class, properties: ['name', 'id', 'addedDate', 'lastModified', 'quantity'])]
class AssemblyBOMEntry extends AbstractDBElement implements UniqueValidatableInterface, TimeStampableInterface
@@ -105,6 +103,13 @@ class AssemblyBOMEntry extends AbstractDBElement implements UniqueValidatableInt
#[Groups(['bom_entry:read', 'bom_entry:write', 'import', 'simple', 'extended', 'full'])]
protected string $mountnames = '';
+ /**
+ * @var string Reference mark on the circuit diagram/PCB
+ */
+ #[ORM\Column(name: 'designator', type: Types::TEXT)]
+ #[Groups(['bom_entry:read', 'bom_entry:write', 'import', 'simple', 'extended', 'full'])]
+ protected string $designator = '';
+
/**
* @var string|null An optional name describing this BOM entry (useful for non-part entries)
*/
@@ -192,6 +197,16 @@ class AssemblyBOMEntry extends AbstractDBElement implements UniqueValidatableInt
return $this;
}
+ public function getDesignator(): string
+ {
+ return $this->designator;
+ }
+
+ public function setDesignator(string $designator): void
+ {
+ $this->designator = $designator;
+ }
+
/**
* @return string
*/
diff --git a/src/Entity/LogSystem/CollectionElementDeleted.php b/src/Entity/LogSystem/CollectionElementDeleted.php
index 15e0001e..20ed580b 100644
--- a/src/Entity/LogSystem/CollectionElementDeleted.php
+++ b/src/Entity/LogSystem/CollectionElementDeleted.php
@@ -61,9 +61,9 @@ use App\Entity\Attachments\UserAttachment;
use App\Entity\Base\AbstractDBElement;
use App\Entity\Contracts\LogWithEventUndoInterface;
use App\Entity\Contracts\NamedElementInterface;
+use App\Entity\Parameters\AssemblyParameter;
use App\Entity\Parameters\PartCustomStateParameter;
use App\Entity\Parts\PartCustomState;
-use App\Entity\Parameters\AssemblyParameter;
use App\Entity\ProjectSystem\Project;
use App\Entity\Parameters\AbstractParameter;
use App\Entity\Parameters\AttachmentTypeParameter;
diff --git a/src/Entity/LogSystem/LogTargetType.php b/src/Entity/LogSystem/LogTargetType.php
index 72efe6c7..29e65c3d 100644
--- a/src/Entity/LogSystem/LogTargetType.php
+++ b/src/Entity/LogSystem/LogTargetType.php
@@ -22,6 +22,8 @@ declare(strict_types=1);
*/
namespace App\Entity\LogSystem;
+use App\Entity\AssemblySystem\Assembly;
+use App\Entity\AssemblySystem\AssemblyBOMEntry;
use App\Entity\Attachments\Attachment;
use App\Entity\Attachments\AttachmentType;
use App\Entity\InfoProviderSystem\BulkInfoProviderImportJob;
@@ -78,6 +80,9 @@ enum LogTargetType: int
case ASSEMBLY_BOM_ENTRY = 24;
case PART_CUSTOM_STATE = 25;
+ case ASSEMBLY = 23;
+ case ASSEMBLY_BOM_ENTRY = 24;
+
/**
* Returns the class name of the target type or null if the target type is NONE.
* @return string|null
diff --git a/src/Entity/Parts/Part.php b/src/Entity/Parts/Part.php
index b0824fc8..e1836f9f 100644
--- a/src/Entity/Parts/Part.php
+++ b/src/Entity/Parts/Part.php
@@ -22,6 +22,7 @@ declare(strict_types=1);
namespace App\Entity\Parts;
+use App\Entity\Parts\PartTraits\AssemblyTrait;
use ApiPlatform\Doctrine\Common\Filter\DateFilterInterface;
use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter;
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
diff --git a/src/Form/AssemblySystem/AssemblyBOMEntryType.php b/src/Form/AssemblySystem/AssemblyBOMEntryType.php
index 851ab815..f8a7a86d 100644
--- a/src/Form/AssemblySystem/AssemblyBOMEntryType.php
+++ b/src/Form/AssemblySystem/AssemblyBOMEntryType.php
@@ -45,12 +45,17 @@ class AssemblyBOMEntryType extends AbstractType
])
->add('name', TextType::class, [
'label' => 'assembly.bom.name',
+ 'help' => 'assembly.bom.name.help',
'required' => false,
])
+ ->add('designator', TextType::class, [
+ 'label' => 'assembly.bom.designator',
+ 'help' => 'assembly.bom.designator.help',
+ 'required' => false
+ ])
->add('mountnames', TextType::class, [
'required' => false,
'label' => 'assembly.bom.mountnames',
- 'empty_data' => '',
'attr' => [
'class' => 'tagsinput',
'data-controller' => 'elements--tagsinput',
diff --git a/src/Helpers/Assemblies/AssemblyPartAggregator.php b/src/Helpers/Assemblies/AssemblyPartAggregator.php
index 2346075a..46495935 100644
--- a/src/Helpers/Assemblies/AssemblyPartAggregator.php
+++ b/src/Helpers/Assemblies/AssemblyPartAggregator.php
@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace App\Helpers\Assemblies;
use App\Entity\AssemblySystem\Assembly;
+use App\Entity\AssemblySystem\AssemblyBOMEntry;
use App\Entity\Parts\Part;
use Dompdf\Dompdf;
use Dompdf\Options;
@@ -61,6 +62,7 @@ class AssemblyPartAggregator
*/
private function processAssembly(Assembly $assembly, float $multiplier, array &$aggregatedParts): void
{
+ /** @var AssemblyBOMEntry $bomEntry */
foreach ($assembly->getBomEntries() as $bomEntry) {
// If the BOM entry refers to a part, add its quantity
if ($bomEntry->getPart() instanceof Part) {
@@ -70,6 +72,8 @@ class AssemblyPartAggregator
$aggregatedParts[$part->getId()] = [
'part' => $part,
'assembly' => $assembly,
+ 'name' => $bomEntry->getName(),
+ 'designator' => $bomEntry->getDesignator(),
'quantity' => $bomEntry->getQuantity(),
'multiplier' => $multiplier,
];
@@ -81,6 +85,8 @@ class AssemblyPartAggregator
$aggregatedParts[] = [
'part' => null,
'assembly' => $assembly,
+ 'name' => $bomEntry->getName(),
+ 'designator' => $bomEntry->getDesignator(),
'quantity' => $bomEntry->getQuantity(),
'multiplier' => $multiplier,
];
diff --git a/src/Services/AssemblySystem/AssemblyBuildHelper.php b/src/Services/AssemblySystem/AssemblyBuildHelper.php
index ce52ef0a..9180f3e8 100644
--- a/src/Services/AssemblySystem/AssemblyBuildHelper.php
+++ b/src/Services/AssemblySystem/AssemblyBuildHelper.php
@@ -103,7 +103,6 @@ class AssemblyBuildHelper
}
/**
- * Returns the assembly BOM entries for which parts are missing in the stock for the given number of builds
* Returns the referenced assembly BOM entries for which parts are missing in the stock for the given number of builds
* @param Assembly $assembly The assembly for which the BOM entries should be checked
* @param int $number_of_builds How often should the assembly be build?
diff --git a/src/Services/ElementTypeNameGenerator.php b/src/Services/ElementTypeNameGenerator.php
index 9ef2a063..a378f5f0 100644
--- a/src/Services/ElementTypeNameGenerator.php
+++ b/src/Services/ElementTypeNameGenerator.php
@@ -22,6 +22,8 @@ declare(strict_types=1);
namespace App\Services;
+use App\Entity\AssemblySystem\Assembly;
+use App\Entity\AssemblySystem\AssemblyBOMEntry;
use App\Entity\Attachments\Attachment;
use App\Entity\Attachments\AttachmentContainingDBElement;
use App\Entity\Attachments\AttachmentType;
diff --git a/src/Services/ImportExportSystem/BOMImporter.php b/src/Services/ImportExportSystem/BOMImporter.php
index 729f10c4..5ed8c388 100644
--- a/src/Services/ImportExportSystem/BOMImporter.php
+++ b/src/Services/ImportExportSystem/BOMImporter.php
@@ -49,7 +49,6 @@ use Symfony\Component\Validator\ConstraintViolation;
*/
class BOMImporter
{
-
private const IMPORT_TYPE_JSON = 'json';
private const IMPORT_TYPE_CSV = 'csv';
private const IMPORT_TYPE_KICAD_PCB = 'kicad_pcbnew';
@@ -64,29 +63,29 @@ class BOMImporter
5 => 'Supplier and ref',
];
+ private readonly PartRepository $partRepository;
+
+ private readonly ManufacturerRepository $manufacturerRepository;
+
+ private readonly CategoryRepository $categoryRepository;
+
+ private readonly DBElementRepository $projectBomEntryRepository;
+
+ private readonly DBElementRepository $assemblyBomEntryRepository;
+
private string $jsonRoot = '';
- private PartRepository $partRepository;
-
- private ManufacturerRepository $manufacturerRepository;
-
- private CategoryRepository $categoryRepository;
-
- private DBElementRepository $projectBomEntryRepository;
-
- private DBElementRepository $assemblyBomEntryRepository;
-
public function __construct(
private readonly EntityManagerInterface $entityManager,
- private readonly TranslatorInterface $translator,
private readonly LoggerInterface $logger,
- private readonly BOMValidationService $validationService
+ private readonly BOMValidationService $validationService,
+ private readonly TranslatorInterface $translator
) {
- $this->partRepository = $entityManager->getRepository(Part::class);
- $this->manufacturerRepository = $entityManager->getRepository(Manufacturer::class);
- $this->categoryRepository = $entityManager->getRepository(Category::class);
- $this->projectBomEntryRepository = $entityManager->getRepository(ProjectBOMEntry::class);
- $this->assemblyBomEntryRepository = $entityManager->getRepository(AssemblyBOMEntry::class);
+ $this->partRepository = $this->entityManager->getRepository(Part::class);
+ $this->manufacturerRepository = $this->entityManager->getRepository(Manufacturer::class);
+ $this->categoryRepository = $this->entityManager->getRepository(Category::class);
+ $this->projectBomEntryRepository = $this->entityManager->getRepository(ProjectBOMEntry::class);
+ $this->assemblyBomEntryRepository = $this->entityManager->getRepository(AssemblyBOMEntry::class);
}
protected function configureOptions(OptionsResolver $resolver): OptionsResolver
@@ -167,22 +166,6 @@ class BOMImporter
return $this->stringToBOMEntries($importObject, $file->getContent(), $options);
}
- /**
- * Validate BOM data before importing
- * @return array Validation result with errors, warnings, and info
- */
- public function validateBOMData(string $data, array $options): array
- {
- $resolver = new OptionsResolver();
- $resolver = $this->configureOptions($resolver);
- $options = $resolver->resolve($options);
-
- return match ($options['type']) {
- 'kicad_pcbnew' => $this->validateKiCADPCB($data),
- 'kicad_schematic' => $this->validateKiCADSchematicData($data, $options),
- default => throw new InvalidArgumentException('Invalid import type!'),
- };
- }
/**
* Handles the conversion of an uploaded file into an ImporterResult for a given project or assembly.
@@ -238,6 +221,23 @@ class BOMImporter
return $this->stringToImporterResult($importObject, $file->getContent(), $options);
}
+ /**
+ * Validate BOM data before importing
+ * @return array Validation result with errors, warnings, and info
+ */
+ public function validateBOMData(string $data, array $options): array
+ {
+ $resolver = new OptionsResolver();
+ $resolver = $this->configureOptions($resolver);
+ $options = $resolver->resolve($options);
+
+ return match ($options['type']) {
+ 'kicad_pcbnew' => $this->validateKiCADPCB($data),
+ 'kicad_schematic' => $this->validateKiCADSchematicData($data, $options),
+ default => throw new InvalidArgumentException('Invalid import type!'),
+ };
+ }
+
/**
* Import string data into an array of BOM entries, which are not yet assigned to a project.
*
@@ -255,7 +255,7 @@ class BOMImporter
return match ($options['type']) {
self::IMPORT_TYPE_KICAD_PCB => $this->parseKiCADPCB($data, $importObject)->getBomEntries(),
- self::IMPORT_TYPE_KICAD_SCHEMATIC => $this->parseKiCADPCB($data, $importObject)->getBomEntries(),
+ self::IMPORT_TYPE_KICAD_SCHEMATIC => $this->parseKiCADSchematic($data, $options),
default => throw new InvalidArgumentException($this->translator->trans('validator.bom_importer.invalid_import_type', [], 'validators')),
};
}
@@ -296,9 +296,8 @@ class BOMImporter
* validates the required fields, and creates BOM entries for each record in the data.
* The BOM entries are added to the provided Project or Assembly, depending on the context.
*
+ * @param string $data The semicolon- or comma-delimited CSV data to be parsed.
* @param Project|Assembly $importObject The object determining the context of the BOM entry (either a Project or Assembly).
- * @param string $data The semicolon- or comma-delimited CSV data to be parsed
- *
* @return ImporterResult The result of the import process, containing the created BOM entries.
*
* @throws UnexpectedValueException If required fields are missing in the provided data.
@@ -858,7 +857,7 @@ class BOMImporter
if (isset($entry['name'])) {
$givenName = trim($entry['name']) === '' ? null : trim ($entry['name']);
- if ($givenName !== null && $part !== null && $part->getName() !== $givenName) {
+ if ($givenName !== null && $bomEntry->getPart() !== null && $bomEntry->getPart()->getName() !== $givenName) {
//Apply different names for parts list entry
$bomEntry->setName(trim($entry['name']) === '' ? null : trim ($entry['name']));
}
@@ -867,7 +866,11 @@ class BOMImporter
}
if (isset($entry['designator'])) {
- $bomEntry->setMountnames(trim($entry['designator']) === '' ? '' : trim($entry['designator']));
+ if ($bomEntry instanceof ProjectBOMEntry) {
+ $bomEntry->setMountnames(trim($entry['designator']) === '' ? '' : trim($entry['designator']));
+ } elseif ($bomEntry instanceof AssemblyBOMEntry) {
+ $bomEntry->setDesignator(trim($entry['designator']) === '' ? '' : trim($entry['designator']));
+ }
}
$bomEntry->setPart($part);
@@ -957,6 +960,7 @@ class BOMImporter
return $out;
}
+
/**
* Builds a JSON-based constraint violation.
*
@@ -964,25 +968,13 @@ class BOMImporter
* The violation includes a message, property path, invalid value, and other contextual information.
* Translations for the violation message can be applied through the translator service.
*
- * @param string $message The translation key for the validation message.
- * @param string $propertyPath The property path where the violation occurred.
- * @param mixed|null $invalidValue The value that caused the violation (optional).
- * @param array $parameters Additional parameters for message placeholders (default is an empty array).
+ * @param string $message The translation key for the validation message.
+ * @param string $propertyPath The property path where the violation occurred.
+ * @param mixed|null $invalidValue The value that caused the violation (optional).
+ * @param array $parameters Additional parameters for message placeholders (default is an empty array).
*
* @return ConstraintViolation The created constraint violation object.
*/
- private function buildJsonViolation(string $message, string $propertyPath, mixed $invalidValue = null, array $parameters = []): ConstraintViolation
- {
- return new ConstraintViolation(
- message: $this->translator->trans($message, $parameters, 'validators'),
- messageTemplate: $message,
- parameters: $parameters,
- root: $this->jsonRoot,
- propertyPath: $propertyPath,
- invalidValue: $invalidValue
- );
- }
-
/**
* Parse KiCad schematic BOM with flexible field mapping
*/
@@ -1460,4 +1452,30 @@ class BOMImporter
return array_values($headers);
}
+
+ /**
+ * Builds a JSON-based constraint violation.
+ *
+ * This method creates a `ConstraintViolation` object that represents a validation error.
+ * The violation includes a message, property path, invalid value, and other contextual information.
+ * Translations for the violation message can be applied through the translator service.
+ *
+ * @param string $message The translation key for the validation message.
+ * @param string $propertyPath The property path where the violation occurred.
+ * @param mixed|null $invalidValue The value that caused the violation (optional).
+ * @param array $parameters Additional parameters for message placeholders (default is an empty array).
+ *
+ * @return ConstraintViolation The created constraint violation object.
+ */
+ private function buildJsonViolation(string $message, string $propertyPath, mixed $invalidValue = null, array $parameters = []): ConstraintViolation
+ {
+ return new ConstraintViolation(
+ message: $this->translator->trans($message, $parameters, 'validators'),
+ messageTemplate: $message,
+ parameters: $parameters,
+ root: $this->jsonRoot,
+ propertyPath: $propertyPath,
+ invalidValue: $invalidValue
+ );
+ }
}
diff --git a/src/Services/ImportExportSystem/EntityExporter.php b/src/Services/ImportExportSystem/EntityExporter.php
index 1dbdaaf4..7b48623e 100644
--- a/src/Services/ImportExportSystem/EntityExporter.php
+++ b/src/Services/ImportExportSystem/EntityExporter.php
@@ -36,6 +36,7 @@ use App\Entity\Parts\StorageLocation;
use App\Entity\Parts\Supplier;
use App\Entity\PriceInformations\Currency;
use App\Entity\ProjectSystem\Project;
+use App\Entity\ProjectSystem\ProjectBOMEntry;
use App\Helpers\Assemblies\AssemblyPartAggregator;
use App\Helpers\FilenameSanatizer;
use App\Serializer\APIPlatform\SkippableItemNormalizer;
@@ -379,49 +380,62 @@ class EntityExporter
],
Project::class => [
'header' => [
- 'Id', 'ParentId', 'Type', 'ProjectNameHierarchical', 'ProjectName', 'ProjectFullName', 'BomQuantity',
- 'BomPartId', 'BomPartIpn', 'BomPartMpnr', 'BomPartName', 'BomDesignator', 'BomPartDescription',
- 'BomMountNames'
+ 'Id', 'ParentId', 'Type', 'ProjectNameHierarchical', 'ProjectName', 'ProjectFullName',
+
+ //BOM relevant attributes
+ 'Quantity', 'PartId', 'PartName', 'Ipn', 'Manufacturer', 'Mpn', 'Name', 'Designator',
+ 'Description', 'MountNames'
],
'processEntity' => fn($entity, $depth) => [
- 'ProjectId' => $entity->getId(),
- 'ParentProjectId' => $entity->getParent()?->getId() ?? '',
+ 'Id' => $entity->getId(),
+ 'ParentId' => $entity->getParent()?->getId() ?? '',
'Type' => 'project',
'ProjectNameHierarchical' => str_repeat('--', $depth) . ' ' . $entity->getName(),
'ProjectName' => $entity->getName(),
'ProjectFullName' => $this->getFullName($entity),
- 'BomQuantity' => '-',
- 'BomPartId' => '-',
- 'BomPartIpn' => '-',
- 'BomPartMpnr' => '-',
- 'BomPartName' => '-',
- 'BomDesignator' => '-',
- 'BomPartDescription' => '-',
- 'BomMountNames' => '-',
+
+ //BOM relevant attributes
+ 'Quantity' => '-',
+ 'PartId' => '-',
+ 'PartName' => '-',
+ 'Ipn' => '-',
+ 'Manufacturer' => '-',
+ 'Mpn' => '-',
+ 'Name' => '-',
+ 'Designator' => '-',
+ 'Description' => '-',
+ 'MountNames' => '-',
],
- 'processBomEntries' => fn($entity, $depth) => array_map(fn(AssemblyBOMEntry $bomEntry) => [
+ 'processBomEntries' => fn($entity, $depth) => array_map(fn(ProjectBOMEntry $bomEntry) => [
'Id' => $entity->getId(),
'ParentId' => '',
'Type' => 'project_bom_entry',
'ProjectNameHierarchical' => str_repeat('--', $depth) . '> ' . $entity->getName(),
'ProjectName' => $entity->getName(),
'ProjectFullName' => $this->getFullName($entity),
- 'BomQuantity' => $bomEntry->getQuantity() ?? '',
- 'BomPartId' => $bomEntry->getPart()?->getId() ?? '',
- 'BomPartIpn' => $bomEntry->getPart()?->getIpn() ?? '',
- 'BomPartMpnr' => $bomEntry->getPart()?->getManufacturerProductNumber() ?? '',
- 'BomPartName' => $bomEntry->getPart()?->getName() ?? '',
- 'BomDesignator' => $bomEntry->getName() ?? '',
- 'BomPartDescription' => $bomEntry->getPart()?->getDescription() ?? '',
- 'BomMountNames' => $bomEntry->getMountNames(),
+
+ //BOM relevant attributes
+ 'Quantity' => $bomEntry->getQuantity() ?? '',
+ 'PartId' => $bomEntry->getPart()?->getId() ?? '',
+ 'PartName' => $bomEntry->getPart()?->getName() ?? '',
+ 'Ipn' => $bomEntry->getPart()?->getIpn() ?? '',
+ 'Manufacturer' => $bomEntry->getPart()?->getManufacturer()?->getName() ?? '',
+ 'Mpn' => $bomEntry->getPart()?->getManufacturerProductNumber() ?? '',
+ 'Name' => $bomEntry->getPart()?->getName() ?? '',
+ 'Designator' => $bomEntry->getMountnames() ?? '',
+ 'Description' => $bomEntry->getPart()?->getDescription() ?? '',
+ 'MountNames' => $bomEntry->getMountNames(),
], $entity->getBomEntries()->toArray()),
],
Assembly::class => [
'header' => [
'Id', 'ParentId', 'Type', 'AssemblyIpn', 'AssemblyNameHierarchical', 'AssemblyName',
- 'AssemblyFullName', 'BomQuantity', 'BomMultiplier', 'BomPartId', 'BomPartIpn', 'BomPartMpnr',
- 'BomPartName', 'BomDesignator', 'BomPartDescription', 'BomMountNames', 'BomReferencedAssemblyId',
- 'BomReferencedAssemblyIpn', 'BomReferencedAssemblyFullName'
+ 'AssemblyFullName',
+
+ //BOM relevant attributes
+ 'Quantity', 'PartId', 'PartName', 'Ipn', 'Manufacturer', 'Mpn', 'Name', 'Designator',
+ 'Description', 'MountNames', 'ReferencedAssemblyId', 'ReferencedAssemblyIpn',
+ 'ReferencedAssemblyFullName'
],
'processEntity' => fn($entity, $depth) => [
'Id' => $entity->getId(),
@@ -431,18 +445,21 @@ class EntityExporter
'AssemblyNameHierarchical' => str_repeat('--', $depth) . ' ' . $entity->getName(),
'AssemblyName' => $entity->getName(),
'AssemblyFullName' => $this->getFullName($entity),
- 'BomQuantity' => '-',
- 'BomMultiplier' => '-',
- 'BomPartId' => '-',
- 'BomPartIpn' => '-',
- 'BomPartMpnr' => '-',
- 'BomPartName' => '-',
- 'BomDesignator' => '-',
- 'BomPartDescription' => '-',
- 'BomMountNames' => '-',
- 'BomReferencedAssemblyId' => '-',
- 'BomReferencedAssemblyIpn' => '-',
- 'BomReferencedAssemblyFullName' => '-',
+
+ //BOM relevant attributes
+ 'Quantity' => '-',
+ 'PartId' => '-',
+ 'PartName' => '-',
+ 'Ipn' => '-',
+ 'Manufacturer' => '-',
+ 'Mpn' => '-',
+ 'Name' => '-',
+ 'Designator' => '-',
+ 'Description' => '-',
+ 'MountNames' => '-',
+ 'ReferencedAssemblyId' => '-',
+ 'ReferencedAssemblyIpn' => '-',
+ 'ReferencedAssemblyFullName' => '-',
],
'processBomEntries' => fn($entity, $depth) => $this->processBomEntriesWithAggregatedParts($entity, $depth),
],
@@ -555,6 +572,7 @@ class EntityExporter
{
$rows = [];
+ /** @var AssemblyBOMEntry $bomEntry */
foreach ($assembly->getBomEntries() as $bomEntry) {
// Add the BOM entry itself
$rows[] = [
@@ -565,18 +583,21 @@ class EntityExporter
'AssemblyNameHierarchical' => str_repeat('--', $depth) . '> ' . $assembly->getName(),
'AssemblyName' => $assembly->getName(),
'AssemblyFullName' => $this->getFullName($assembly),
- 'BomQuantity' => $bomEntry->getQuantity() ?? '',
- 'BomMultiplier' => '',
- 'BomPartId' => $bomEntry->getPart()?->getId() ?? '-',
- 'BomPartIpn' => $bomEntry->getPart()?->getIpn() ?? '-',
- 'BomPartMpnr' => $bomEntry->getPart()?->getManufacturerProductNumber() ?? '-',
- 'BomPartName' => $bomEntry->getPart()?->getName() ?? '-',
- 'BomDesignator' => $bomEntry->getName() ?? '-',
- 'BomPartDescription' => $bomEntry->getPart()?->getDescription() ?? '-',
- 'BomMountNames' => $bomEntry->getMountNames(),
- 'BomReferencedAssemblyId' => $bomEntry->getReferencedAssembly()?->getId() ?? '-',
- 'BomReferencedAssemblyIpn' => $bomEntry->getReferencedAssembly()?->getIpn() ?? '-',
- 'BomReferencedAssemblyFullName' => $this->getFullName($bomEntry->getReferencedAssembly() ?? null),
+
+ //BOM relevant attributes
+ 'Quantity' => $bomEntry->getQuantity() ?? '',
+ 'PartId' => $bomEntry->getPart()?->getId() ?? '-',
+ 'PartName' => $bomEntry->getPart()?->getName() ?? '-',
+ 'Ipn' => $bomEntry->getPart()?->getIpn() ?? '-',
+ 'Manufacturer' => $bomEntry->getPart()?->getManufacturer()?->getName() ?? '-',
+ 'Mpn' => $bomEntry->getPart()?->getManufacturerProductNumber() ?? '-',
+ 'Name' => $bomEntry->getName() ?? '-',
+ 'Designator' => $bomEntry->getDesignator(),
+ 'MountNames' => $bomEntry->getMountNames(),
+ 'Description' => $bomEntry->getPart()?->getDescription() ?? '-',
+ 'ReferencedAssemblyId' => $bomEntry->getReferencedAssembly()?->getId() ?? '-',
+ 'ReferencedAssemblyIpn' => $bomEntry->getReferencedAssembly()?->getIpn() ?? '-',
+ 'ReferencedAssemblyFullName' => $this->getFullName($bomEntry->getReferencedAssembly() ?? null),
];
// If a referenced assembly exists, add aggregated parts
@@ -597,18 +618,21 @@ class EntityExporter
'AssemblyNameHierarchical' => '',
'AssemblyName' => $partAssembly ? $partAssembly->getName() : '',
'AssemblyFullName' => $this->getFullName($partAssembly),
- 'BomQuantity' => $partData['quantity'],
- 'BomMultiplier' => $partData['multiplier'],
- 'BomPartId' => $partData['part']?->getId(),
- 'BomPartIpn' => $partData['part']?->getIpn(),
- 'BomPartMpnr' => $partData['part']?->getManufacturerProductNumber(),
- 'BomPartName' => $partData['part']?->getName(),
- 'BomDesignator' => $partData['part']?->getName(),
- 'BomPartDescription' => $partData['part']?->getDescription(),
- 'BomMountNames' => '-',
- 'BomReferencedAssemblyId' => '-',
- 'BomReferencedAssemblyIpn' => '-',
- 'BomReferencedAssemblyFullName' => '-',
+
+ //BOM relevant attributes
+ 'Quantity' => $partData['quantity'],
+ 'PartId' => $partData['part']?->getId(),
+ 'PartName' => $partData['part']?->getName(),
+ 'Ipn' => $partData['part']?->getIpn(),
+ 'Manufacturer' => $partData['part']?->getManufacturer()?->getName(),
+ 'Mpn' => $partData['part']?->getManufacturerProductNumber(),
+ 'Name' => $partData['name'] ?? '',
+ 'Designator' => $partData['designator'],
+ 'Description' => $partData['part']?->getDescription(),
+ 'MountNames' => '-',
+ 'ReferencedAssemblyId' => '-',
+ 'ReferencedAssemblyIpn' => '-',
+ 'ReferencedAssemblyFullName' => '-',
];
}
}
diff --git a/src/Services/Trees/ToolsTreeBuilder.php b/src/Services/Trees/ToolsTreeBuilder.php
index e37a6e85..f454804f 100644
--- a/src/Services/Trees/ToolsTreeBuilder.php
+++ b/src/Services/Trees/ToolsTreeBuilder.php
@@ -51,15 +51,8 @@ use Symfony\Contracts\Translation\TranslatorInterface;
*/
class ToolsTreeBuilder
{
- public function __construct(
- protected TranslatorInterface $translator,
- protected UrlGeneratorInterface $urlGenerator,
- protected TagAwareCacheInterface $cache,
- protected UserCacheKeyGenerator $keyGenerator,
- protected Security $security,
- protected ?array $dataSourceSynonyms = [],
- ) {
- $this->dataSourceSynonyms = $dataSourceSynonyms ?? [];
+ public function __construct(protected TranslatorInterface $translator, protected UrlGeneratorInterface $urlGenerator, protected TagAwareCacheInterface $cache, protected UserCacheKeyGenerator $keyGenerator, protected Security $security)
+ {
}
/**
@@ -174,43 +167,43 @@ class ToolsTreeBuilder
}
if ($this->security->isGranted('read', new Category())) {
$nodes[] = (new TreeViewNode(
- $this->getTranslatedDataSourceOrSynonym('category', 'tree.tools.edit.categories', $this->translator->getLocale()),
+ $this->translator->trans('tree.tools.edit.categories'),
$this->urlGenerator->generate('category_new')
))->setIcon('fa-fw fa-treeview fa-solid fa-tags');
}
if ($this->security->isGranted('read', new Project())) {
$nodes[] = (new TreeViewNode(
- $this->getTranslatedDataSourceOrSynonym('project', 'tree.tools.edit.projects', $this->translator->getLocale()),
+ $this->translator->trans('tree.tools.edit.projects'),
$this->urlGenerator->generate('project_new')
))->setIcon('fa-fw fa-treeview fa-solid fa-archive');
}
if ($this->security->isGranted('read', new Assembly())) {
$nodes[] = (new TreeViewNode(
- $this->getTranslatedDataSourceOrSynonym('assembly', 'tree.tools.edit.assemblies', $this->translator->getLocale()),
+ $this->translator->trans('tree.tools.edit.assemblies'),
$this->urlGenerator->generate('assembly_new')
))->setIcon('fa-fw fa-treeview fa-solid fa-list');
}
if ($this->security->isGranted('read', new Supplier())) {
$nodes[] = (new TreeViewNode(
- $this->getTranslatedDataSourceOrSynonym('supplier', 'tree.tools.edit.suppliers', $this->translator->getLocale()),
+ $this->translator->trans('tree.tools.edit.suppliers'),
$this->urlGenerator->generate('supplier_new')
))->setIcon('fa-fw fa-treeview fa-solid fa-truck');
}
if ($this->security->isGranted('read', new Manufacturer())) {
$nodes[] = (new TreeViewNode(
- $this->getTranslatedDataSourceOrSynonym('manufacturer', 'tree.tools.edit.manufacturer', $this->translator->getLocale()),
+ $this->translator->trans('tree.tools.edit.manufacturer'),
$this->urlGenerator->generate('manufacturer_new')
))->setIcon('fa-fw fa-treeview fa-solid fa-industry');
}
if ($this->security->isGranted('read', new StorageLocation())) {
$nodes[] = (new TreeViewNode(
- $this->getTranslatedDataSourceOrSynonym('storagelocation', 'tree.tools.edit.storelocation', $this->translator->getLocale()),
+ $this->translator->trans('tree.tools.edit.storelocation'),
$this->urlGenerator->generate('store_location_new')
))->setIcon('fa-fw fa-treeview fa-solid fa-cube');
}
if ($this->security->isGranted('read', new Footprint())) {
$nodes[] = (new TreeViewNode(
- $this->getTranslatedDataSourceOrSynonym('footprint', 'tree.tools.edit.footprint', $this->translator->getLocale()),
+ $this->translator->trans('tree.tools.edit.footprint'),
$this->urlGenerator->generate('footprint_new')
))->setIcon('fa-fw fa-treeview fa-solid fa-microchip');
}
@@ -324,22 +317,4 @@ class ToolsTreeBuilder
return $nodes;
}
-
- protected function getTranslatedDataSourceOrSynonym(string $dataSource, string $translationKey, string $locale): string
- {
- $currentTranslation = $this->translator->trans($translationKey);
-
- // Call alternatives from DataSourcesynonyms (if available)
- if (!empty($this->dataSourceSynonyms[$dataSource][$locale])) {
- $alternativeTranslation = $this->dataSourceSynonyms[$dataSource][$locale];
-
- // Use alternative translation when it deviates from the standard translation
- if ($alternativeTranslation !== $currentTranslation) {
- return $alternativeTranslation;
- }
- }
-
- // Otherwise return the standard translation
- return $currentTranslation;
- }
}
diff --git a/src/Services/Trees/TreeViewGenerator.php b/src/Services/Trees/TreeViewGenerator.php
index d5358bfa..3a097902 100644
--- a/src/Services/Trees/TreeViewGenerator.php
+++ b/src/Services/Trees/TreeViewGenerator.php
@@ -68,11 +68,9 @@ class TreeViewGenerator
protected TranslatorInterface $translator,
private readonly UrlGeneratorInterface $router,
private readonly SidebarSettings $sidebarSettings,
- protected ?array $dataSourceSynonyms = [],
) {
$this->rootNodeEnabled = $this->sidebarSettings->rootNodeEnabled;
$this->rootNodeExpandedByDefault = $this->sidebarSettings->rootNodeExpanded;
- $this->dataSourceSynonyms = $dataSourceSynonyms ?? [];
}
/**
@@ -228,16 +226,14 @@ class TreeViewGenerator
protected function entityClassToRootNodeString(string $class): string
{
- $locale = $this->translator->getLocale();
-
return match ($class) {
- Category::class => $this->getTranslatedOrSynonym('category', $locale),
- StorageLocation::class => $this->getTranslatedOrSynonym('storelocation', $locale),
- Footprint::class => $this->getTranslatedOrSynonym('footprint', $locale),
- Manufacturer::class => $this->getTranslatedOrSynonym('manufacturer', $locale),
- Supplier::class => $this->getTranslatedOrSynonym('supplier', $locale),
- Project::class => $this->getTranslatedOrSynonym('project', $locale),
- Assembly::class => $this->getTranslatedOrSynonym('assembly', $locale),
+ Category::class => $this->translator->trans('category.labelp'),
+ StorageLocation::class => $this->translator->trans('storelocation.labelp'),
+ Footprint::class => $this->translator->trans('footprint.labelp'),
+ Manufacturer::class => $this->translator->trans('manufacturer.labelp'),
+ Supplier::class => $this->translator->trans('supplier.labelp'),
+ Project::class => $this->translator->trans('project.labelp'),
+ Assembly::class => $this->translator->trans('assembly.labelp'),
default => $this->translator->trans('tree.root_node.text'),
};
}
@@ -294,22 +290,4 @@ class TreeViewGenerator
return $repo->getGenericNodeTree($parent); //@phpstan-ignore-line
});
}
-
- protected function getTranslatedOrSynonym(string $key, string $locale): string
- {
- $currentTranslation = $this->translator->trans($key . '.labelp');
-
- // Call alternatives from DataSourcesynonyms (if available)
- if (!empty($this->dataSourceSynonyms[$key][$locale])) {
- $alternativeTranslation = $this->dataSourceSynonyms[$key][$locale];
-
- // Use alternative translation when it deviates from the standard translation
- if ($alternativeTranslation !== $currentTranslation) {
- return $alternativeTranslation;
- }
- }
-
- // Otherwise return the standard translation
- return $currentTranslation;
- }
}
diff --git a/src/Settings/BehaviorSettings/AssemblyBomTableColumns.php b/src/Settings/BehaviorSettings/AssemblyBomTableColumns.php
index da8557c2..2833a3df 100644
--- a/src/Settings/BehaviorSettings/AssemblyBomTableColumns.php
+++ b/src/Settings/BehaviorSettings/AssemblyBomTableColumns.php
@@ -28,12 +28,20 @@ use Symfony\Contracts\Translation\TranslatorInterface;
enum AssemblyBomTableColumns : string implements TranslatableInterface
{
-
case NAME = "name";
case ID = "id";
case QUANTITY = "quantity";
case IPN = "ipn";
case DESCRIPTION = "description";
+ case CATEGORY = "category";
+ case MANUFACTURER = "manufacturer";
+ case DESIGNATOR = "designator";
+ case MOUNTNAMES = "mountnames";
+ case STORAGE_LOCATION = "storage_location";
+ case AMOUNT = "amount";
+ case ADDED_DATE = "addedDate";
+ case LAST_MODIFIED = "lastModified";
+ case EDIT = "edit";
public function trans(TranslatorInterface $translator, ?string $locale = null): string
{
diff --git a/src/Settings/BehaviorSettings/TableSettings.php b/src/Settings/BehaviorSettings/TableSettings.php
index 5c7455e2..cfe7e71b 100644
--- a/src/Settings/BehaviorSettings/TableSettings.php
+++ b/src/Settings/BehaviorSettings/TableSettings.php
@@ -97,8 +97,8 @@ class TableSettings
#[Assert\Unique()]
#[Assert\All([new Assert\Type(AssemblyBomTableColumns::class)])]
- public array $assembliesBomDefaultColumns = [AssemblyBomTableColumns::QUANTITY, AssemblyTableColumns::ID, AssemblyTableColumns::IPN,
- AssemblyTableColumns::NAME, AssemblyTableColumns::DESCRIPTION];
+ public array $assembliesBomDefaultColumns = [AssemblyBomTableColumns::QUANTITY, AssemblyBomTableColumns::ID,
+ AssemblyBomTableColumns::IPN, AssemblyBomTableColumns::NAME, AssemblyBomTableColumns::DESCRIPTION];
#[SettingsParameter(label: new TM("settings.behavior.table.preview_image_min_width"),
formOptions: ['attr' => ['min' => 1, 'max' => 100]],
diff --git a/templates/admin/assembly_admin.html.twig b/templates/admin/assembly_admin.html.twig
index 2e68a3da..b6bf6d09 100644
--- a/templates/admin/assembly_admin.html.twig
+++ b/templates/admin/assembly_admin.html.twig
@@ -3,9 +3,7 @@
{# @var entity App\Entity\AssemblySystem\Assembly #}
{% block card_title %}
- {% set dataSourceName = get_data_source_name('assembly', 'assembly.caption') %}
- {% set translatedSource = 'assembly.caption'|trans %}
- {% if dataSourceName != translatedSource %}{{ 'datasource.synonym'|trans({'%name%': translatedSource, '%synonym%': dataSourceName}) }}{% else %}{{ translatedSource }}{% endif %}
+ {% trans %}assembly.caption{% endtrans %}
{% endblock %}
{% block edit_title %}
diff --git a/templates/assemblies/info/info.html.twig b/templates/assemblies/info/info.html.twig
index 6b6a4c89..aeb039af 100644
--- a/templates/assemblies/info/info.html.twig
+++ b/templates/assemblies/info/info.html.twig
@@ -71,7 +71,7 @@
-