diff --git a/migrations/Version20250304081039.php b/migrations/Version20250304081039.php index ccdb24ac..2c04dfb0 100644 --- a/migrations/Version20250304081039.php +++ b/migrations/Version20250304081039.php @@ -18,42 +18,42 @@ final class Version20250304081039 extends AbstractMultiPlatformMigration { $this->addSql(<<<'SQL' CREATE TABLE assemblies ( - id INT AUTO_INCREMENT NOT NULL, - parent_id INT DEFAULT NULL, - id_preview_attachment INT DEFAULT NULL, - name VARCHAR(255) NOT NULL, - comment LONGTEXT NOT NULL, - not_selectable TINYINT(1) NOT NULL, - alternative_names LONGTEXT DEFAULT NULL, - order_quantity INT NOT NULL, - status VARCHAR(64) DEFAULT NULL, - order_only_missing_parts TINYINT(1) NOT NULL, - description LONGTEXT NOT NULL, - last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, - datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, - INDEX IDX_5F3832C0727ACA70 (parent_id), - INDEX IDX_5F3832C0EA7100A1 (id_preview_attachment), + id INT AUTO_INCREMENT NOT NULL, + parent_id INT DEFAULT NULL, + id_preview_attachment INT DEFAULT NULL, + name VARCHAR(255) NOT NULL, + comment LONGTEXT NOT NULL, + not_selectable TINYINT(1) NOT NULL, + alternative_names LONGTEXT DEFAULT NULL, + order_quantity INT NOT NULL, + status VARCHAR(64) DEFAULT NULL, + order_only_missing_parts TINYINT(1) NOT NULL, + description LONGTEXT NOT NULL, + last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + INDEX IDX_5F3832C0727ACA70 (parent_id), + INDEX IDX_5F3832C0EA7100A1 (id_preview_attachment), PRIMARY KEY(id) ) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` SQL); $this->addSql(<<<'SQL' CREATE TABLE assembly_bom_entries ( - id INT AUTO_INCREMENT NOT NULL, - id_assembly INT DEFAULT NULL, - id_part INT DEFAULT NULL, - id_project INT DEFAULT NULL, - quantity DOUBLE PRECISION NOT NULL, - mountnames LONGTEXT NOT NULL, - name VARCHAR(255) DEFAULT NULL, - comment LONGTEXT NOT NULL, - price NUMERIC(11, 5) DEFAULT NULL, - price_currency_id INT DEFAULT NULL, - last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, - datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, - INDEX IDX_8C74887E2F180363 (id_assembly), - INDEX IDX_8C74887EC22F6CC4 (id_part), - INDEX IDX_8C74887EF12E799E (id_project), - INDEX IDX_8C74887E3FFDCD60 (price_currency_id), + id INT AUTO_INCREMENT NOT NULL, + id_assembly INT DEFAULT NULL, + id_part INT DEFAULT NULL, + id_project INT DEFAULT NULL, + quantity DOUBLE PRECISION NOT NULL, + mountnames LONGTEXT NOT NULL, + name VARCHAR(255) DEFAULT NULL, + comment LONGTEXT NOT NULL, + price NUMERIC(11, 5) DEFAULT NULL, + price_currency_id INT DEFAULT NULL, + last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + INDEX IDX_8C74887E2F180363 (id_assembly), + INDEX IDX_8C74887EC22F6CC4 (id_part), + INDEX IDX_8C74887EF12E799E (id_project), + INDEX IDX_8C74887E3FFDCD60 (price_currency_id), PRIMARY KEY(id) ) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` SQL); @@ -109,7 +109,7 @@ final class Version20250304081039 extends AbstractMultiPlatformMigration { $this->addSql(<<<'SQL' CREATE TABLE assemblies ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, parent_id INTEGER DEFAULT NULL, id_preview_attachment INTEGER DEFAULT NULL, order_quantity INTEGER NOT NULL, @@ -120,7 +120,7 @@ final class Version20250304081039 extends AbstractMultiPlatformMigration last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, status VARCHAR(64) DEFAULT NULL, - ipn VARCHAR(100) DEFAULT NULL, + ipn VARCHAR(100) DEFAULT NULL, description CLOB NOT NULL, alternative_names CLOB DEFAULT NULL, CONSTRAINT FK_5F3832C0727ACA70 FOREIGN KEY (parent_id) REFERENCES assemblies (id) NOT DEFERRABLE INITIALLY IMMEDIATE, @@ -145,7 +145,7 @@ 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_project INTEGER DEFAULT NULL, id_referenced_assembly INTEGER DEFAULT NULL, price_currency_id INTEGER DEFAULT NULL, quantity DOUBLE PRECISION NOT NULL, @@ -158,8 +158,8 @@ final class Version20250304081039 extends AbstractMultiPlatformMigration 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 + 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 ) SQL); $this->addSql(<<<'SQL' @@ -193,19 +193,19 @@ final class Version20250304081039 extends AbstractMultiPlatformMigration { $this->addSql(<<<'SQL' CREATE TABLE assemblies ( - id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, - name VARCHAR(255) NOT NULL, - last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, - datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, - comment TEXT NOT NULL, - not_selectable BOOLEAN NOT NULL, - alternative_names TEXT DEFAULT NULL, - order_quantity INT NOT NULL, - status VARCHAR(64) DEFAULT NULL, - order_only_missing_parts BOOLEAN NOT NULL, - description TEXT NOT NULL, - parent_id INT DEFAULT NULL, - id_preview_attachment INT DEFAULT NULL, + id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, + name VARCHAR(255) NOT NULL, + last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, + datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, + comment TEXT NOT NULL, + not_selectable BOOLEAN NOT NULL, + alternative_names TEXT DEFAULT NULL, + order_quantity INT NOT NULL, + status VARCHAR(64) DEFAULT NULL, + order_only_missing_parts BOOLEAN NOT NULL, + description TEXT NOT NULL, + parent_id INT DEFAULT NULL, + id_preview_attachment INT DEFAULT NULL, PRIMARY KEY(id) ) SQL); @@ -217,18 +217,18 @@ final class Version20250304081039 extends AbstractMultiPlatformMigration SQL); $this->addSql(<<<'SQL' CREATE TABLE assembly_bom_entries ( - 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, - comment TEXT NOT NULL, - price NUMERIC(11, 5) DEFAULT NULL, + 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, + comment TEXT NOT NULL, + price NUMERIC(11, 5) DEFAULT NULL, price_currency_id INT DEFAULT NULL, - last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, - datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, + last_modified TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, + datetime_added TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL, PRIMARY KEY(id) ) SQL); diff --git a/migrations/Version20250304154507.php b/migrations/Version20250304154507.php index bb25b802..649e9c0a 100644 --- a/migrations/Version20250304154507.php +++ b/migrations/Version20250304154507.php @@ -44,8 +44,8 @@ final class Version20250304154507 extends AbstractMultiPlatformMigration public function sqLiteUp(Schema $schema): void { $this->addSql(<<<'SQL' - CREATE TEMPORARY TABLE __temp__parts AS - SELECT + CREATE TEMPORARY TABLE __temp__parts AS + SELECT id, id_preview_attachment, id_category, @@ -82,7 +82,7 @@ final class Version20250304154507 extends AbstractMultiPlatformMigration eda_info_exclude_from_board, eda_info_exclude_from_sim, eda_info_kicad_symbol, - eda_info_kicad_footprint + eda_info_kicad_footprint FROM parts SQL); $this->addSql('DROP TABLE parts'); @@ -148,8 +148,8 @@ final class Version20250304154507 extends AbstractMultiPlatformMigration id_part_unit, id_manufacturer, order_orderdetails_id, - built_project_id, - datetime_added, + built_project_id, + datetime_added, name, last_modified, needs_review, @@ -164,12 +164,12 @@ final class Version20250304154507 extends AbstractMultiPlatformMigration manufacturer_product_number, manufacturing_status, order_quantity, - manual_order, + manual_order, ipn, provider_reference_provider_key, provider_reference_provider_id, provider_reference_provider_url, - provider_reference_last_updated, + provider_reference_last_updated, eda_info_reference_prefix, eda_info_value, eda_info_invisible, @@ -223,8 +223,8 @@ final class Version20250304154507 extends AbstractMultiPlatformMigration public function sqLiteDown(Schema $schema): void { $this->addSql(<<<'SQL' - CREATE TEMPORARY TABLE __temp__parts AS - SELECT + CREATE TEMPORARY TABLE __temp__parts AS + SELECT id, id_preview_attachment, id_category, @@ -326,8 +326,8 @@ final class Version20250304154507 extends AbstractMultiPlatformMigration id_part_unit, id_manufacturer, order_orderdetails_id, - built_project_id, - datetime_added, + built_project_id, + datetime_added, name, last_modified, needs_review, @@ -342,12 +342,12 @@ final class Version20250304154507 extends AbstractMultiPlatformMigration manufacturer_product_number, manufacturing_status, order_quantity, - manual_order, + manual_order, ipn, provider_reference_provider_key, provider_reference_provider_id, provider_reference_provider_url, - provider_reference_last_updated, + provider_reference_last_updated, eda_info_reference_prefix, eda_info_value, eda_info_invisible, diff --git a/migrations/Version20250310160354.php b/migrations/Version20250310160354.php new file mode 100644 index 00000000..542fcac2 --- /dev/null +++ b/migrations/Version20250310160354.php @@ -0,0 +1,27 @@ +addSql('ALTER TABLE assembly_bom_entries RENAME INDEX idx_8c74887e2f180363 TO IDX_8C74887E4AD2039E'); + $this->addSql('ALTER TABLE project_bom_entries ADD id_assembly INT DEFAULT NULL AFTER id_part'); + $this->addSql('ALTER TABLE project_bom_entries ADD CONSTRAINT FK_1AA2DD314AD2039E FOREIGN KEY (id_assembly) REFERENCES assemblies (id)'); + $this->addSql('CREATE INDEX IDX_1AA2DD314AD2039E ON project_bom_entries (id_assembly)'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE assembly_bom_entries RENAME INDEX idx_8c74887e4ad2039e TO IDX_8C74887E2F180363'); + $this->addSql('ALTER TABLE project_bom_entries DROP FOREIGN KEY FK_1AA2DD314AD2039E'); + $this->addSql('DROP INDEX IDX_1AA2DD314AD2039E ON project_bom_entries'); + $this->addSql('ALTER TABLE project_bom_entries DROP id_assembly'); + } +} diff --git a/src/Controller/PartController.php b/src/Controller/PartController.php index ec08b540..29abfad8 100644 --- a/src/Controller/PartController.php +++ b/src/Controller/PartController.php @@ -207,7 +207,7 @@ final class PartController extends AbstractController #[Route(path: '/new', name: 'part_new')] #[Route(path: '/{id}/clone', name: 'part_clone')] - #[Route(path: '/new_build_part/{project_id}', name: 'part_new_build_part')] + #[Route(path: '/new_build_part_project/{project_id}', name: 'part_new_build_part_project')] #[Route(path: '/new_build_part_assembly/{assembly_id}', name: 'part_new_build_part_assembly')] public function new( Request $request, diff --git a/src/DataTables/AssemblyBomEntriesDataTable.php b/src/DataTables/AssemblyBomEntriesDataTable.php index e506dccd..48d65040 100644 --- a/src/DataTables/AssemblyBomEntriesDataTable.php +++ b/src/DataTables/AssemblyBomEntriesDataTable.php @@ -206,7 +206,7 @@ class AssemblyBomEntriesDataTable implements DataTableTypeInterface //Apply the user configured order and visibility and add the columns to the table $this->csh->applyVisibilityAndConfigureColumns($dataTable, $this->visible_columns,"TABLE_ASSEMBLIES_BOM_DEFAULT_COLUMNS"); - $dataTable->addOrderBy('name'); + $dataTable->addOrderBy('name', DataTable::SORT_ASCENDING); $dataTable->createAdapter(ORMAdapter::class, [ 'entity' => Attachment::class, diff --git a/src/Entity/AssemblySystem/AssemblyBOMEntry.php b/src/Entity/AssemblySystem/AssemblyBOMEntry.php index 9bca209d..eb24fd3e 100644 --- a/src/Entity/AssemblySystem/AssemblyBOMEntry.php +++ b/src/Entity/AssemblySystem/AssemblyBOMEntry.php @@ -37,6 +37,7 @@ 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; diff --git a/src/Entity/Base/AbstractDBElement.php b/src/Entity/Base/AbstractDBElement.php index 27d60c86..7768f7aa 100644 --- a/src/Entity/Base/AbstractDBElement.php +++ b/src/Entity/Base/AbstractDBElement.php @@ -22,9 +22,6 @@ declare(strict_types=1); namespace App\Entity\Base; -use App\Entity\AssemblySystem\Assembly; -use App\Entity\AssemblySystem\AssemblyBOMEntry; -use App\Entity\Attachments\AssemblyAttachment; use App\Entity\Attachments\AttachmentType; use App\Entity\Attachments\Attachment; use App\Entity\Attachments\AttachmentTypeAttachment; @@ -38,6 +35,7 @@ use App\Entity\Attachments\MeasurementUnitAttachment; use App\Entity\Attachments\PartAttachment; use App\Entity\Attachments\PartCustomStateAttachment; use App\Entity\Attachments\ProjectAttachment; +use App\Entity\Attachments\AssemblyAttachment; use App\Entity\Attachments\StorageLocationAttachment; use App\Entity\Attachments\SupplierAttachment; use App\Entity\Attachments\UserAttachment; @@ -47,6 +45,8 @@ use App\Entity\PriceInformations\Pricedetail; use App\Entity\Parts\PartCustomState; use App\Entity\ProjectSystem\Project; use App\Entity\ProjectSystem\ProjectBOMEntry; +use App\Entity\AssemblySystem\Assembly; +use App\Entity\AssemblySystem\AssemblyBOMEntry; use App\Entity\Parts\Footprint; use App\Entity\UserSystem\Group; use App\Entity\Parts\Manufacturer; @@ -87,12 +87,15 @@ use Symfony\Component\Serializer\Annotation\Groups; 'part_attachment' => PartAttachment::class, 'part_custom_state_attachment' => PartCustomStateAttachment::class, 'project_attachment' => ProjectAttachment::class, + 'assembly_attachment' => AssemblyAttachment::class, 'storelocation_attachment' => StorageLocationAttachment::class, 'supplier_attachment' => SupplierAttachment::class, 'user_attachment' => UserAttachment::class, 'category' => Category::class, 'project' => Project::class, 'project_bom_entry' => ProjectBOMEntry::class, + 'assembly' => Assembly::class, + 'assembly_bom_entry' => AssemblyBOMEntry::class, 'footprint' => Footprint::class, 'group' => Group::class, 'manufacturer' => Manufacturer::class, diff --git a/src/Entity/ProjectSystem/Project.php b/src/Entity/ProjectSystem/Project.php index a103d694..36a96377 100644 --- a/src/Entity/ProjectSystem/Project.php +++ b/src/Entity/ProjectSystem/Project.php @@ -108,6 +108,7 @@ class Project extends AbstractStructuralDBElement #[Groups(['extended', 'full', 'import'])] #[ORM\OneToMany(mappedBy: 'project', targetEntity: ProjectBOMEntry::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[UniqueObjectCollection(message: 'project.bom_entry.part_already_in_bom', fields: ['part'])] + #[UniqueObjectCollection(message: 'project.bom_entry.assembly_already_in_bom', fields: ['assembly'])] #[UniqueObjectCollection(message: 'project.bom_entry.name_already_in_bom', fields: ['name'])] protected Collection $bom_entries; diff --git a/src/Entity/ProjectSystem/ProjectBOMEntry.php b/src/Entity/ProjectSystem/ProjectBOMEntry.php index b2a3b2e9..f8caa5d5 100644 --- a/src/Entity/ProjectSystem/ProjectBOMEntry.php +++ b/src/Entity/ProjectSystem/ProjectBOMEntry.php @@ -35,6 +35,7 @@ use ApiPlatform\Metadata\Post; use ApiPlatform\OpenApi\Model\Operation; use ApiPlatform\Serializer\Filter\PropertyFilter; use App\ApiPlatform\Filter\LikeFilter; +use App\Entity\AssemblySystem\Assembly; use App\Entity\Contracts\TimeStampableInterface; use App\Repository\DBElementRepository; use App\Validator\UniqueValidatableInterface; @@ -104,7 +105,10 @@ class ProjectBOMEntry extends AbstractDBElement implements UniqueValidatableInte /** * @var string|null An optional name describing this BOM entry (useful for non-part entries) */ - #[Assert\Expression('this.getPart() !== null or this.getName() !== null', message: 'validator.project.bom_entry.name_or_part_needed')] + #[Assert\Expression( + 'this.getPart() !== null or this.getAssembly() !== null or (this.getName() !== null and this.getName() != "")', + message: 'validator.project.bom_entry.part_or_assembly_needed' + )] #[ORM\Column(type: Types::STRING, nullable: true)] #[Groups(['bom_entry:read', 'bom_entry:write', 'import', 'simple', 'extended', 'full'])] protected ?string $name = null; @@ -132,6 +136,18 @@ class ProjectBOMEntry extends AbstractDBElement implements UniqueValidatableInte #[Groups(['bom_entry:read', 'bom_entry:write', 'full'])] protected ?Part $part = null; + /** + * @var Assembly|null The associated assembly + */ + #[Assert\Expression( + '(this.getPart() === null or this.getAssembly() === null) and (this.getName() === null or (this.getName() != null and this.getName() != ""))', + message: 'validator.project.bom_entry.only_part_or_assembly_allowed' + )] + #[ORM\ManyToOne(targetEntity: Assembly::class, inversedBy: 'assembly_bom_entries')] + #[ORM\JoinColumn(name: 'id_assembly')] + #[Groups(['bom_entry:read', 'bom_entry:write', ])] + protected ?Assembly $assembly = null; + /** * @var BigDecimal|null The price of this non-part BOM entry */ @@ -224,6 +240,16 @@ class ProjectBOMEntry extends AbstractDBElement implements UniqueValidatableInte return $this; } + public function getAssembly(): ?Assembly + { + return $this->assembly; + } + + public function setAssembly(?Assembly $assembly): void + { + $this->assembly = $assembly; + } + /** * Returns the price of this BOM entry, if existing. * Prices are only valid on non-Part BOM entries. @@ -261,6 +287,15 @@ class ProjectBOMEntry extends AbstractDBElement implements UniqueValidatableInte return $this->part instanceof Part; } + /** + * Checks whether this BOM entry is a assembly associated BOM entry or not. + * @return bool True if this BOM entry is a assembly associated BOM entry, false otherwise. + */ + public function isAssemblyBomEntry(): bool + { + return $this->assembly instanceof Assembly; + } + #[Assert\Callback] public function validate(ExecutionContextInterface $context, $payload): void { @@ -322,6 +357,7 @@ class ProjectBOMEntry extends AbstractDBElement implements UniqueValidatableInte return [ 'name' => $this->getName(), 'part' => $this->getPart()?->getID(), + 'assembly' => $this->getAssembly()?->getID(), ]; } } diff --git a/src/Form/ProjectSystem/ProjectAddPartsType.php b/src/Form/ProjectSystem/ProjectAddPartsType.php index 61f72c41..c5dbe99f 100644 --- a/src/Form/ProjectSystem/ProjectAddPartsType.php +++ b/src/Form/ProjectSystem/ProjectAddPartsType.php @@ -59,6 +59,7 @@ class ProjectAddPartsType extends AbstractType ], 'constraints' => [ new UniqueObjectCollection(message: 'project.bom_entry.part_already_in_bom', fields: ['part']), + new UniqueObjectCollection(message: 'project.bom_entry.assembly_already_in_bom', fields: ['assembly']), new UniqueObjectCollection(message: 'project.bom_entry.name_already_in_bom', fields: ['name']), ] ]); diff --git a/src/Helpers/Projects/ProjectBuildRequest.php b/src/Helpers/Projects/ProjectBuildRequest.php index 24bb5eb7..3254565a 100644 --- a/src/Helpers/Projects/ProjectBuildRequest.php +++ b/src/Helpers/Projects/ProjectBuildRequest.php @@ -22,10 +22,13 @@ declare(strict_types=1); */ namespace App\Helpers\Projects; +use App\Entity\AssemblySystem\Assembly; +use App\Entity\AssemblySystem\AssemblyBOMEntry; use App\Entity\Parts\Part; use App\Entity\Parts\PartLot; use App\Entity\ProjectSystem\Project; use App\Entity\ProjectSystem\ProjectBOMEntry; +use App\Helpers\Assemblies\AssemblyBuildRequest; use App\Validator\Constraints\ProjectSystem\ValidProjectBuildRequest; /** @@ -79,7 +82,7 @@ final class ProjectBuildRequest //Completely reset the array $this->withdraw_amounts = []; - //Now create an array for each BOM entry + //Now create an array for each part BOM entry foreach ($this->getPartBomEntries() as $bom_entry) { $remaining_amount = $this->getNeededAmountForBOMEntry($bom_entry); foreach($this->getPartLotsForBOMEntry($bom_entry) as $lot) { @@ -88,6 +91,21 @@ final class ProjectBuildRequest $remaining_amount -= max(0, $this->withdraw_amounts[$lot->getID()]); } } + + //Now create an array for each assembly BOM entry + foreach ($this->getAssemblyBomEntries() as $assemblyBomEntry) { + $assemblyBuildRequest = new AssemblyBuildRequest($assemblyBomEntry->getAssembly(), $this->number_of_builds); + + //Add fields for assembly bom entries + foreach ($assemblyBuildRequest->getPartBomEntries() as $partBomEntry) { + $remaining_amount = $assemblyBuildRequest->getNeededAmountForBOMEntry($partBomEntry) * $assemblyBomEntry->getQuantity(); + + foreach ($assemblyBuildRequest->getPartLotsForBOMEntry($partBomEntry) as $lot) { + $this->withdraw_amounts[$lot->getID()] = min($remaining_amount, $lot->getAmount()); + $remaining_amount -= max(0, $this->withdraw_amounts[$lot->getID()]); + } + } + } } /** @@ -230,12 +248,77 @@ final class ProjectBuildRequest { $this->ensureBOMEntryValid($projectBOMEntry); - if (!$projectBOMEntry->getPart() instanceof Part) { + if (!$projectBOMEntry->getPart() instanceof Part && !$projectBOMEntry->getAssembly() instanceof Assembly) { return null; } //Filter out all lots which have unknown instock - return $projectBOMEntry->getPart()->getPartLots()->filter(fn (PartLot $lot) => !$lot->isInstockUnknown())->toArray(); + if ($projectBOMEntry->getPart() instanceof Part) { + return $projectBOMEntry->getPart()->getPartLots()->filter(fn (PartLot $lot) => !$lot->isInstockUnknown())->toArray(); + } elseif ($projectBOMEntry->getAssembly() instanceof Assembly) { + $assemblyBuildRequest = new AssemblyBuildRequest($projectBOMEntry->getAssembly(), $this->number_of_builds); + + //Add fields for assembly bom entries + $result = []; + foreach ($assemblyBuildRequest->getPartBomEntries() as $assemblyBOMEntry) { + $tmp = $assemblyBOMEntry->getPart()->getPartLots()->filter(fn (PartLot $lot) => !$lot->isInstockUnknown())->toArray(); + $result = array_merge($result, $tmp); + } + + return $result; + } + + return null; + } + + /** + * Returns all available assembly BOM-entries with no part assigned. + * @return AssemblyBOMEntry[]|null Returns null if no entries found + */ + public function getAssemblyBomEntriesWithoutPart(ProjectBOMEntry $projectBOMEntry): ?array + { + $this->ensureBOMEntryValid($projectBOMEntry); + + if (!$projectBOMEntry->getAssembly() instanceof Assembly) { + return null; + } + + $assemblyBuildRequest = new AssemblyBuildRequest($projectBOMEntry->getAssembly(), $this->number_of_builds); + + $result = []; + + foreach ($assemblyBuildRequest->getBomEntries() as $assemblyBOMEntry) { + if ($assemblyBOMEntry->getPart() === null) { + $result[] = $assemblyBOMEntry; + } + } + + return count($result) > 0 ? $result : null; + } + + /** + * Returns all available assembly BOM-entries with no part assigned. + * @return AssemblyBOMEntry[]|null Returns null if no entries found + */ + public function getAssemblyBomEntriesWithPartNoStock(ProjectBOMEntry $projectBOMEntry): ?array + { + $this->ensureBOMEntryValid($projectBOMEntry); + + if (!$projectBOMEntry->getAssembly() instanceof Assembly) { + return null; + } + + $assemblyBuildRequest = new AssemblyBuildRequest($projectBOMEntry->getAssembly(), $this->number_of_builds); + + $result = []; + + foreach ($assemblyBuildRequest->getBomEntries() as $assemblyBOMEntry) { + if ($assemblyBOMEntry->getPart() instanceof Part && $assemblyBOMEntry->getPart()->getPartLots()->filter(fn (PartLot $lot) => !$lot->isInstockUnknown())->count() === 0) { + $result[] = $assemblyBOMEntry; + } + } + + return count($result) > 0 ? $result : null; } /** @@ -266,6 +349,15 @@ final class ProjectBuildRequest return $this->project->getBomEntries()->filter(fn(ProjectBOMEntry $entry) => $entry->isPartBomEntry())->toArray(); } + /** + * Returns the all assembly bom entries that have to be built. + * @return ProjectBOMEntry[] + */ + public function getAssemblyBomEntries(): array + { + return $this->project->getBomEntries()->filter(fn(ProjectBOMEntry $entry) => $entry->isAssemblyBomEntry())->toArray(); + } + /** * Returns which project should be build */ diff --git a/src/Services/AssemblySystem/AssemblyBuildHelper.php b/src/Services/AssemblySystem/AssemblyBuildHelper.php index b7f2df3c..430eb5d2 100644 --- a/src/Services/AssemblySystem/AssemblyBuildHelper.php +++ b/src/Services/AssemblySystem/AssemblyBuildHelper.php @@ -74,11 +74,11 @@ class AssemblyBuildHelper continue; } - //The maximum buildable count for the whole project is the minimum of all BOM entries + //The maximum buildable count for the whole assembly is the minimum of all BOM entries if ($bom_entry->getPart() !== null) { $maximum_buildable_count = min($maximum_buildable_count, $this->getMaximumBuildableCountForBOMEntry($bom_entry)); } elseif ($bom_entry->getReferencedAssembly() !== null) { - $maximum_buildable_count = min($maximum_buildable_count, $this->projectBuildHelper->getMaximumBuildableCount($bom_entry->getReferencedAssembly())); + $maximum_buildable_count = min($maximum_buildable_count, $this->getMaximumBuildableCount($bom_entry->getReferencedAssembly())); } } @@ -105,7 +105,7 @@ class AssemblyBuildHelper } /** - * Returns the project BOM entries for which parts are missing in the stock for the given number of builds + * Returns the 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? * @return AssemblyBOMEntry[] diff --git a/src/Services/ImportExportSystem/BOMImporter.php b/src/Services/ImportExportSystem/BOMImporter.php index ecda3c5e..f36462fb 100644 --- a/src/Services/ImportExportSystem/BOMImporter.php +++ b/src/Services/ImportExportSystem/BOMImporter.php @@ -76,8 +76,6 @@ class BOMImporter private DBElementRepository $assemblyBOMEntryRepository; - private TranslatorInterface $translator; - public function __construct( private readonly EntityManagerInterface $entityManager, private readonly TranslatorInterface $translator, @@ -89,7 +87,6 @@ class BOMImporter $this->categoryRepository = $entityManager->getRepository(Category::class); $this->projectBOMEntryRepository = $entityManager->getRepository(ProjectBOMEntry::class); $this->assemblyBOMEntryRepository = $entityManager->getRepository(AssemblyBOMEntry::class); - $this->translator = $translator; } protected function configureOptions(OptionsResolver $resolver): OptionsResolver @@ -257,7 +254,8 @@ class BOMImporter $options = $resolver->resolve($options); return match ($options['type']) { - self::IMPORT_TYPE_KICAD_PCB => $this->parseKiCADPCB($data, $objectType)->getBomEntries(), + self::IMPORT_TYPE_KICAD_PCB => $this->parseKiCADPCB($data, $importObject)->getBomEntries(), + self::IMPORT_TYPE_KICAD_SCHEMATIC => $this->parseKiCADPCB($data, $importObject)->getBomEntries(), default => throw new InvalidArgumentException($this->translator->trans('validator.bom_importer.invalid_import_type', [], 'validators')), }; } @@ -285,8 +283,8 @@ class BOMImporter return match ($options['type']) { self::IMPORT_TYPE_KICAD_PCB => $this->parseKiCADPCB($data, $importObject), - self::IMPORT_TYPE_JSON => $this->parseJson($data, $importObject), - self::IMPORT_TYPE_CSV => $this->parseCsv($data, $importObject), + self::IMPORT_TYPE_JSON => $this->parseJson($importObject, $data), + self::IMPORT_TYPE_CSV => $this->parseCsv($importObject, $data), default => $defaultImporterResult, }; } diff --git a/src/Services/ProjectSystem/ProjectBuildHelper.php b/src/Services/ProjectSystem/ProjectBuildHelper.php index 269c7e4c..d7ba9e6c 100644 --- a/src/Services/ProjectSystem/ProjectBuildHelper.php +++ b/src/Services/ProjectSystem/ProjectBuildHelper.php @@ -22,10 +22,13 @@ declare(strict_types=1); */ namespace App\Services\ProjectSystem; +use App\Entity\AssemblySystem\AssemblyBOMEntry; use App\Entity\Parts\Part; use App\Entity\ProjectSystem\Project; use App\Entity\ProjectSystem\ProjectBOMEntry; +use App\Helpers\Assemblies\AssemblyBuildRequest; use App\Helpers\Projects\ProjectBuildRequest; +use App\Services\AssemblySystem\AssemblyBuildHelper; use App\Services\Parts\PartLotWithdrawAddHelper; /** @@ -33,8 +36,10 @@ use App\Services\Parts\PartLotWithdrawAddHelper; */ class ProjectBuildHelper { - public function __construct(private readonly PartLotWithdrawAddHelper $withdraw_add_helper) - { + public function __construct( + private readonly PartLotWithdrawAddHelper $withdrawAddHelper, + private readonly AssemblyBuildHelper $assemblyBuildHelper + ) { } /** @@ -66,12 +71,16 @@ class ProjectBuildHelper $maximum_buildable_count = PHP_INT_MAX; foreach ($project->getBomEntries() as $bom_entry) { //Skip BOM entries without a part (as we can not determine that) - if (!$bom_entry->isPartBomEntry()) { + if (!$bom_entry->isPartBomEntry() && $bom_entry->getAssembly() === null) { continue; } //The maximum buildable count for the whole project is the minimum of all BOM entries - $maximum_buildable_count = min($maximum_buildable_count, $this->getMaximumBuildableCountForBOMEntry($bom_entry)); + if ($bom_entry->getPart() !== null) { + $maximum_buildable_count = min($maximum_buildable_count, $this->getMaximumBuildableCountForBOMEntry($bom_entry)); + } elseif ($bom_entry->getAssembly() !== null) { + $maximum_buildable_count = min($maximum_buildable_count, $this->assemblyBuildHelper->getMaximumBuildableCount($bom_entry->getAssembly())); + } } return $maximum_buildable_count; @@ -97,10 +106,10 @@ class ProjectBuildHelper } /** - * Returns the project BOM entries for which parts are missing in the stock for the given number of builds + * Returns the project or assembly BOM entries for which parts are missing in the stock for the given number of builds * @param Project $project The project for which the BOM entries should be checked * @param int $number_of_builds How often should the project be build? - * @return ProjectBOMEntry[] + * @return ProjectBOMEntry[]|AssemblyBOMEntry[] */ public function getNonBuildableProjectBomEntries(Project $project, int $number_of_builds = 1): array { @@ -108,24 +117,29 @@ class ProjectBuildHelper throw new \InvalidArgumentException('The number of builds must be greater than 0!'); } - $non_buildable_entries = []; + $nonBuildableEntries = []; foreach ($project->getBomEntries() as $bomEntry) { $part = $bomEntry->getPart(); //Skip BOM entries without a part (as we can not determine that) - if (!$part instanceof Part) { + if (!$part instanceof Part && $bomEntry->getAssembly() === null) { continue; } - $amount_sum = $part->getAmountSum(); + if ($bomEntry->getPart() !== null) { + $amount_sum = $part->getAmountSum(); - if ($amount_sum < $bomEntry->getQuantity() * $number_of_builds) { - $non_buildable_entries[] = $bomEntry; + if ($amount_sum < $bomEntry->getQuantity() * $number_of_builds) { + $nonBuildableEntries[] = $bomEntry; + } + } elseif ($bomEntry->getAssembly() !== null) { + $nonBuildableAssemblyEntries = $this->assemblyBuildHelper->getNonBuildableAssemblyBomEntries($bomEntry->getAssembly(), $number_of_builds); + $nonBuildableEntries = array_merge($nonBuildableEntries, $nonBuildableAssemblyEntries); } } - return $non_buildable_entries; + return $nonBuildableEntries; } /** @@ -133,22 +147,37 @@ class ProjectBuildHelper * The ProjectBuildRequest has to be validated before!! * You have to flush changes to DB afterward */ - public function doBuild(ProjectBuildRequest $buildRequest): void + public function doBuild(ProjectBuildRequest $projectBuildRequest): void { - $message = $buildRequest->getComment(); - $message .= ' (Project build: '.$buildRequest->getProject()->getName().')'; + $message = $projectBuildRequest->getComment(); + $message .= ' (Project build: '.$projectBuildRequest->getProject()->getName().')'; - foreach ($buildRequest->getPartBomEntries() as $bom_entry) { - foreach ($buildRequest->getPartLotsForBOMEntry($bom_entry) as $part_lot) { - $amount = $buildRequest->getLotWithdrawAmount($part_lot); + foreach ($projectBuildRequest->getPartBomEntries() as $bomEntry) { + foreach ($projectBuildRequest->getPartLotsForBOMEntry($bomEntry) as $partLot) { + $amount = $projectBuildRequest->getLotWithdrawAmount($partLot); if ($amount > 0) { - $this->withdraw_add_helper->withdraw($part_lot, $amount, $message); + $this->withdrawAddHelper->withdraw($partLot, $amount, $message); } } } - if ($buildRequest->getAddBuildsToBuildsPart()) { - $this->withdraw_add_helper->add($buildRequest->getBuildsPartLot(), $buildRequest->getNumberOfBuilds(), $message); + foreach ($projectBuildRequest->getAssemblyBomEntries() as $bomEntry) { + $assemblyBuildRequest = new AssemblyBuildRequest($bomEntry->getAssembly(), $projectBuildRequest->getNumberOfBuilds()); + + //Add fields for assembly bom entries + foreach ($assemblyBuildRequest->getPartBomEntries() as $partBomEntry) { + foreach ($assemblyBuildRequest->getPartLotsForBOMEntry($partBomEntry) as $partLot) { + //Read amount from build configuration of the projectBuildRequest + $amount = $projectBuildRequest->getLotWithdrawAmount($partLot); + if ($amount > 0) { + $this->withdrawAddHelper->withdraw($partLot, $amount, $message); + } + } + } + } + + if ($projectBuildRequest->getAddBuildsToBuildsPart()) { + $this->withdrawAddHelper->add($projectBuildRequest->getBuildsPartLot(), $projectBuildRequest->getNumberOfBuilds(), $message); } } } diff --git a/src/Services/Trees/ToolsTreeBuilder.php b/src/Services/Trees/ToolsTreeBuilder.php index 083e22f2..e37a6e85 100644 --- a/src/Services/Trees/ToolsTreeBuilder.php +++ b/src/Services/Trees/ToolsTreeBuilder.php @@ -147,7 +147,7 @@ class ToolsTreeBuilder $this->translator->trans('info_providers.search.title'), $this->urlGenerator->generate('info_providers_search') ))->setIcon('fa-treeview fa-fw fa-solid fa-cloud-arrow-down'); - + $nodes[] = (new TreeViewNode( $this->translator->trans('info_providers.bulk_import.manage_jobs'), $this->urlGenerator->generate('bulk_info_provider_manage') diff --git a/templates/admin/assembly_admin.html.twig b/templates/admin/assembly_admin.html.twig index def4eeb2..758c4cbc 100644 --- a/templates/admin/assembly_admin.html.twig +++ b/templates/admin/assembly_admin.html.twig @@ -62,4 +62,4 @@ {% endif %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/templates/assemblies/build/_form.html.twig b/templates/assemblies/build/_form.html.twig index 97cace56..aaaa7824 100644 --- a/templates/assemblies/build/_form.html.twig +++ b/templates/assemblies/build/_form.html.twig @@ -87,4 +87,4 @@ {{ form_row(form.submit) }} -{{ form_end(form) }} \ No newline at end of file +{{ form_end(form) }} diff --git a/templates/assemblies/import_bom.html.twig b/templates/assemblies/import_bom.html.twig index 89f504c2..bfbecf8d 100644 --- a/templates/assemblies/import_bom.html.twig +++ b/templates/assemblies/import_bom.html.twig @@ -105,6 +105,8 @@ {{ 'assembly.bom_import.template.kicad_pcbnew.exptected_columns.note'|trans|raw }} {{ 'assembly.bom_import.template.kicad_pcbnew.table'|trans|raw }} + + {{ 'assembly.bom_import.template.json.table'|trans|raw }} diff --git a/templates/assemblies/info/_bom.html.twig b/templates/assemblies/info/_bom.html.twig new file mode 100644 index 00000000..6a2ca3e0 --- /dev/null +++ b/templates/assemblies/info/_bom.html.twig @@ -0,0 +1,22 @@ +{% import "components/datatables.macro.html.twig" as datatables %} + +
+ + + {% trans %}assembly.info.bom_add_parts{% endtrans %} + + + +
+ +{{ datatables.datatable(datatable, 'elements/datatables/datatables', 'assemblies') }} \ No newline at end of file diff --git a/templates/assemblies/info/_info_card.html.twig b/templates/assemblies/info/_info_card.html.twig index 2d0c535b..c89c77fe 100644 --- a/templates/assemblies/info/_info_card.html.twig +++ b/templates/assemblies/info/_info_card.html.twig @@ -37,6 +37,12 @@ {% trans %}entity.info.attachments.tab{% endtrans %} {% endif %} + {% if assembly.parameters is not empty %} + + + {% trans %}entity.info.parameters.tab{% endtrans %} + + {% endif %} {% if assembly.comment is not empty %} @@ -102,6 +108,15 @@ {% endif %} + {% if assembly.parameters is not empty %} +
+ {% for name, parameters in assembly.groupedParameters %} + {% if name is not empty %}
{{ name }}
{% endif %} + {{ helper.parameters_table(assembly) }} + {% endfor %} +
+ {% endif %} + {% if assembly.comment is not empty %}
@@ -115,4 +130,4 @@
- \ No newline at end of file + diff --git a/templates/assemblies/info/_subassemblies.html.twig b/templates/assemblies/info/_subassemblies.html.twig new file mode 100644 index 00000000..8c92c5e9 --- /dev/null +++ b/templates/assemblies/info/_subassemblies.html.twig @@ -0,0 +1,28 @@ + + + + + + + + + + + {% for subassembly in assembly.children %} + + + + + + + {% endfor %} + +
{% trans %}name.label{% endtrans %}{% trans %}description.label{% endtrans %}# {% trans %}assembly.info.bom_entries_count{% endtrans %}# {% trans %}assembly.info.sub_assemblies_count{% endtrans %}
{# Name #} + {{ subassembly.name }} + {# Description #} + {{ subassembly.description | format_markdown }} + + {{ subassembly.bomEntries | length }} + + {{ subassembly.children | length }} +
\ No newline at end of file diff --git a/templates/assemblies/info/info.html.twig b/templates/assemblies/info/info.html.twig index 5a419e36..2ef6cf25 100644 --- a/templates/assemblies/info/info.html.twig +++ b/templates/assemblies/info/info.html.twig @@ -70,8 +70,18 @@ {% trans %}assembly.info.info.label{% endtrans %} + {% if assembly.children is not empty %} + + {% endif %}
{% endif %} + {% if assembly.parameters is not empty %} + + {% endif %}
@@ -103,13 +123,26 @@
{% include "assemblies/info/_part.html.twig" %} + {% if assembly.children is not empty %} +
+ {% include "assemblies/info/_subassemblies.html.twig" %} +
+ {% endif %} +
+ {% include "assemblies/info/_bom.html.twig" %}
{% include "assemblies/info/_builds.html.twig" %}
- {% include "assemblies/info/_attachments_info.html.twig" with {"assembly": assembly} %} + {% include "assemblies/info/_attachments_info.html.twig" with {"part": assembly} %} +
+
+ {% for name, parameters in assembly.groupedParameters %} + {% if name is not empty %}
{{ name }}
{% endif %} + {{ helper.parameters_table(assembly.parameters) }} + {% endfor %}
-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/templates/form/collection_types_layout.html.twig b/templates/form/collection_types_layout.html.twig index 96b71bf0..def23500 100644 --- a/templates/form/collection_types_layout.html.twig +++ b/templates/form/collection_types_layout.html.twig @@ -6,7 +6,7 @@ {# expand button #} {% trans %}project.bom.quantity{% endtrans %} - {% trans %}project.bom.part{% endtrans %} + {% trans %}project.bom.partOrAssembly{% endtrans %} {% trans %}project.bom.name{% endtrans %} {# Remove button #} @@ -41,9 +41,11 @@ {{ form_widget(form.quantity) }} {{ form_errors(form.quantity) }} - - {{ form_widget(form.part) }} + + {{ form_row(form.part) }} {{ form_errors(form.part) }} + {{ form_widget(form.assembly) }} + {{ form_errors(form.assembly) }} {{ form_widget(form.name) }} diff --git a/templates/form/collection_types_layout_assembly.html.twig b/templates/form/collection_types_layout_assembly.html.twig index 6dc6d49a..98cb73b6 100644 --- a/templates/form/collection_types_layout_assembly.html.twig +++ b/templates/form/collection_types_layout_assembly.html.twig @@ -80,4 +80,4 @@ -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/templates/projects/build/_form.html.twig b/templates/projects/build/_form.html.twig index b25ca81e..7775fd2a 100644 --- a/templates/projects/build/_form.html.twig +++ b/templates/projects/build/_form.html.twig @@ -27,7 +27,9 @@ {% if bom_entry.part %} - {{ bom_entry.part.name }} {% if bom_entry.name %}({{ bom_entry.name }}){% endif %} + {{ 'projects.build.form.part'|trans({'%name%': bom_entry.part.name}) }} {% if bom_entry.name %}({{ bom_entry.name }}){% endif %} + {% elseif bom_entry.assembly %} + {{ 'projects.build.form.assembly'|trans({'%name%': bom_entry.assembly.name}) }} {% if bom_entry.name %}({{ bom_entry.name }}){% endif %} {% else %} {{ bom_entry.name }} {% endif %} @@ -45,9 +47,29 @@ {% set lots = build_request.partLotsForBOMEntry(bom_entry) %} + {% set assemblyBomEntriesWithoutPart = build_request.assemblyBomEntriesWithoutPart(bom_entry) %} + {% set assemblyBomEntriesWithPartNoStock = build_request.assemblyBomEntriesWithPartNoStock(bom_entry) %} {% if lots is not null %} + {% set previousLabel = null %} + {% for lot in lots %} {# @var lot \App\Entity\Parts\PartLot #} + + {% set label = '' %} + {% if form["lot_"~lot.id].vars.label is defined and form["lot_"~lot.id].vars.label is not empty %} + {% set label = form["lot_"~lot.id].vars.label %} + {% endif %} + + {% if label != '' and (previousLabel is null or label != previousLabel) %} +
+ +
+ {% endif %} + + {% set previousLabel = label %} +
-
+
/ {{ lot.amount | format_amount(lot.part.partUnit) }} {% trans %}project.builds.stocked{% endtrans %}
{% endfor %} {% endif %} + {% if assemblyBomEntriesWithoutPart is not null %} + {% for bomEntryWithoutPart in assemblyBomEntriesWithoutPart %} +
+ +
+
+ / {% trans %}project.builds.no_stock{% endtrans %} +
+
+ {% endfor %} + {% endif %} + {% if assemblyBomEntriesWithPartNoStock is not null %} + {% for bomEntryWithPartNoStock in assemblyBomEntriesWithPartNoStock %} +
+
+ +
+
+ / {% trans %}project.builds.no_stock{% endtrans %} +
+
+
+ {% endfor %} + {% endif %} {% endfor %} diff --git a/translations/messages.cs.xlf b/translations/messages.cs.xlf index 21b1416e..2b0c280b 100644 --- a/translations/messages.cs.xlf +++ b/translations/messages.cs.xlf @@ -4813,6 +4813,18 @@ Pokud jste to provedli nesprávně nebo pokud počítač již není důvěryhodn Název + + + project.bom.assembly + Sestava + + + + + project.bom.partOrAssembly + Výběr + + Part-DB1\src\DataTables\PartsDataTable.php:178 @@ -9894,6 +9906,18 @@ Element 3 Díl + + + project.bom.assembly + Baugruppe + + + + + project.bom.partOrAssembly + Auswahl + + project.bom.add_entry @@ -10290,6 +10314,12 @@ Element 3 k dispozici + + + project.builds.no_stock + není uveden žádný sklad + + project.builds.needed @@ -10362,6 +10392,12 @@ Element 3 Cílový inventář + + + project.build.builds_part_lot_label + %name% (%quantity% požadováno) + + project.builds.number_of_builds @@ -13540,6 +13576,634 @@ Vezměte prosím na vědomí, že se nemůžete vydávat za uživatele se zakáz Z bezpečnostních důvodů redigováno + + + part.table.name.value.for_part + %value% (Součást) + + + + + part.table.name.value.for_assembly + %value% (Sestava) + + + + + assembly.label + Sestava + + + + + assembly.caption + Sestava + + + + + perm.assemblies + Sestavy + + + + + assembly_bom_entry.label + Součásti + + + + + assembly.labelp + Sestavy + + + + + assembly.edit + Upravit sestavu + + + + + assembly.new + Nová sestava + + + + + assembly.edit.associated_build_part + Přidružená součást + + + + + assembly.edit.associated_build_part.add + Přidat součást + + + + + assembly.edit.associated_build.hint + Tato součást představuje vyrobené instance sestavy. Zadejte, pokud jsou vyrobené instance potřeba. Pokud ne, počet součástí bude použit až při sestavení daného projektu. + + + + + assembly.edit.bom.import_bom + Importovat součásti + + + + + log.database_updated.failed + __log.database_updated.failed + + + + + log.database_updated.old_version + __log.database_updated.old_version + + + + + log.database_updated.new_version + __log.database_updated.new_version + + + + + tree.tools.edit.assemblies + Sestavy + + + + + assembly.bom_import.flash.success + %count% součástí úspěšně importováno do sestavy. + + + + + assembly.bom_import.flash.invalid_entries + Chyba ověření! Zkontrolujte svůj importovaný soubor! + + + + + assembly.bom_import.flash.invalid_file + Soubor nelze importovat. Zkontrolujte, zda jste vybrali správný typ souboru. Chybová zpráva: %message% + + + + + assembly.bom.quantity + Množství + + + + + assembly.bom.mountnames + Názvy osazení + + + + + assembly.bom.instockAmount + Stav na skladě + + + + + assembly.info.title + Info o sestavě + + + + + assembly.info.info.label + Informace + + + + + assembly.info.sub_assemblies.label + Podskupina + + + + + assembly.info.builds.label + Sestavení + + + + + assembly.info.bom_add_parts + Přidat součásti + + + + + assembly.builds.check_assembly_status + "%assembly_status%". Měli byste zkontrolovat, zda opravdu chcete sestavu postavit s tímto stavem!]]> + + + + + assembly.builds.build_not_possible + Sestavení není možné: Nedostatek součástí + + + + + assembly.builds.following_bom_entries_miss_instock + Není dostatek součástí na skladě pro postavení tohoto projektu %number_of_builds% krát. Následující součásti nejsou skladem v dostatečném množství. + + + + + assembly.builds.build_possible + Sestavení je možné + + + + + assembly.builds.number_of_builds_possible + %max_builds% kusů této sestavy.]]> + + + + + assembly.builds.number_of_builds + Počet sestavení + + + + + assembly.build.btn_build + Sestavit + + + + + assembly.builds.no_stocked_builds + Počet skladovaných vyrobených instancí + + + + + assembly.info.bom_entries_count + Součásti + + + + + assembly.info.sub_assemblies_count + Podskupiny + + + + + assembly.builds.stocked + skladem + + + + + assembly.builds.needed + potřebné + + + + + assembly.add_parts_to_assembly + Přidat součásti do sestavy + + + + + assembly.bom.name + Název + + + + + assembly.bom.comment + Poznámky + + + + + assembly.builds.following_bom_entries_miss_instock_n + Není dostatek součástí na skladě pro sestavení této sestavy %number_of_builds% krát. Následující součásti nejsou skladem: + + + + + assembly.build.help + Vyberte, ze kterých zásob se mají brát potřebné součásti pro sestavení (a v jakém množství). Zaškrtněte políčko u každého dílu, pokud jste jej odebrali, nebo použijte horní políčko k výběru všech naráz. + + + + + assembly.build.required_qty + Požadované množství + + + + + assembly.import_bom + Importovat součásti do sestavy + + + + + assembly.bom.part + Součást + + + + + assembly.bom.add_entry + Přidat položku + + + + + assembly.bom.price + Cena + + + + + assembly.build.dont_check_quantity + Neověřovat množství + + + + + assembly.build.dont_check_quantity.help + Pokud je tato volba vybrána, budou vybraná množství odstraněna ze skladu bez ohledu na to, zda je méně nebo více součástí, než je skutečně potřeba pro sestavení sestavy. + + + + + assembly.build.add_builds_to_builds_part + Přidat vyrobené instance do součásti sestavy + + + + + assembly.bom_import.type + Typ + + + + + assembly.bom_import.type.json + JSON pro sestavu + + + + + assembly.bom_import.type.kicad_pcbnew + CSV (KiCAD Pcbnew BOM) + + + + + assembly.bom_import.clear_existing_bom + Smazat existující položky před importem + + + + + assembly.bom_import.clear_existing_bom.help + Pokud je tato možnost vybrána, budou všechny již existující součásti sestavy smazány a nahrazeny importovanými daty součástí. + + + + + assembly.import_bom.template.header.json + Šablona importu JSON pro sestavu + + + + + assembly.import_bom.template.header.kicad_pcbnew + Šablona importu CSV (KiCAD Pcbnew BOM) pro sestavu + + + + + assembly.bom_import.template.entry.name + Název součásti v sestavě + + + + + assembly.bom_import.template.entry.part.mpnr + Unikátní číslo produktu u výrobce + + + + + assembly.bom_import.template.entry.part.ipn + Unikátní IPN součásti + + + + + assembly.bom_import.template.entry.part.name + Unikátní název součásti + + + + + assembly.bom_import.template.entry.part.manufacturer.name + Unikátní jméno výrobce + + + + + assembly.bom_import.template.entry.part.category.name + Unikátní název kategorie + + + + + assembly.bom_import.template.json.table + + + + + Pole + Podmínka + Datový typ + Popis + + + + + quantity + Povinné + Číslo s plovoucí desetinnou čárkou (Float) + Musí být uvedeno a obsahovat hodnotu s plovoucí desetinnou čárkou (Float) větší než 0,0. + + + name + Volitelné + Řetězec (String) + Pokud je přítomen, musí být neprázdný řetězec. + + + part + Volitelné + Objekt/Array + + Pokud je uvedeno, musí to být objekt/array a minimálně jedno pole musí být vyplněno: +
    +
  • part.id
  • +
  • part.name
  • +
+ + + + part.id + Volitelné + Celé číslo (Integer) + Celé číslo (Integer) > 0. Odpovídá internímu číselnému ID součástky v Part-DB. + + + part.name + Volitelné + Řetězec (String) + Neprázdný řetězec, pokud není zadáno part.mpnr nebo part.ipn. + + + part.mpnr + Volitelné + Řetězec (String) + Neprázdný řetězec, pokud není zadáno part.name nebo part.ipn. + + + part.ipn + Volitelné + Řetězec (String) + Neprázdný řetězec, pokud není zadáno part.name nebo part.mpnr. + + + part.description + Volitelné + Řetězec nebo null + Pokud je přítomen, musí být neprázdný řetězec nebo null. + + + part.manufacturer + Volitelné + Objekt/Array + + Pokud je přítomen, musí to být objekt/array a minimálně jedno pole musí být vyplněno: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + Volitelné + Celé číslo (Integer) + Celé číslo (Integer) > 0. Odpovídá internímu číselnému ID výrobce. + + + manufacturer.name + Volitelné + Řetězec (String) + Neprázdný řetězec, pokud není uvedeno manufacturer.id. + + + part.category + Volitelné + Objekt/Array + + Pokud je přítomen, musí to být objekt/array a minimálně jedno pole musí být vyplněno: +
    +
  • category.id
  • +
  • category.name
  • +
+ + + + category.id + Volitelné + Celé číslo (Integer) + Celé číslo (Integer) > 0. Odpovídá internímu číselnému ID kategorie součástky. + + + category.name + Volitelné + Řetězec (String) + Neprázdný řetězec, pokud není uvedeno category.id. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.exptected_columns + Očekávané sloupce: + + + + + assembly.bom_import.template.kicad_pcbnew.exptected_columns.note + + Poznámka: Neprobíhá přiřazení ke konkrétním součástem ze správy kategorií.

+ ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.table + + + + + Pole + Podmínka + Datový typ + Popis + + + + + Id + Volitelný + Celé číslo (Integer) + Volný údaj. Jedinečné identifikační číslo pro každou součástku. + + + Designator + Volitelný + Řetězec (String) + Volný údaj. Jedinečný referenční označovač součástky na desce plošných spojů, např. „R1“ pro rezistor 1. Používá se pro název osazení součástky v rámci skupiny součástek. + + + Package + Volitelný + Řetězec (String) + Volný údaj. Pouzdro nebo tvar součástky, např. „0805“ pro SMD rezistory. + + + Množství + Povinný + Celé číslo (Integer) + Počet identických součástek, které jsou potřeba k vytvoření jedné instance sestavy. + + + Určení + Povinný + Řetězec (String) + Popis nebo funkce součástky, např. hodnota rezistoru „10kΩ“ nebo hodnota kondenzátoru „100nF“. Používá se pro název položky v BOM. + + + Dodavatel a ref + Volitelný + Řetězec (String) + Volný údaj. Může obsahovat např. specifické údaje distributora. + + + + ]]> + + + + + + typeahead.parts.part.name + %name% (součást) + + + + + typeahead.parts.assembly.name + %name% (sestava) + + + + + projects.build.form.part + Součást "%name%" + + + + + projects.build.form.assembly + Sestava "%name%" + + + + + projects.build.form.assembly.bom.entry + %name% (potřebné množství: %quantity%) + + + + + projects.build.form.assembly.bom.entry.no.stock + není skladem + + project.bom_import.map_fields diff --git a/translations/messages.da.xlf b/translations/messages.da.xlf index f4a3881d..7e6a06bb 100644 --- a/translations/messages.da.xlf +++ b/translations/messages.da.xlf @@ -4820,6 +4820,18 @@ Bemærk også, at uden to-faktor-godkendelse er din konto ikke længere så godt Navn + + + project.bom.assembly + Montering + + + + + project.bom.partOrAssembly + Valg + + Part-DB1\src\DataTables\PartsDataTable.php:178 @@ -9920,6 +9932,18 @@ Element 3 Komponent + + + project.bom.assembly + Baugruppe + + + + + project.bom.partOrAssembly + Auswahl + + project.bom.add_entry @@ -10316,6 +10340,12 @@ Element 3 På lager + + + project.builds.no_stock + intet lager angivet + + project.builds.needed @@ -10388,6 +10418,12 @@ Element 3 Mål mængde + + + project.build.builds_part_lot_label + %name% (%quantity% påkrævet) + + project.builds.number_of_builds diff --git a/translations/messages.de.xlf b/translations/messages.de.xlf index 51252368..293d758a 100644 --- a/translations/messages.de.xlf +++ b/translations/messages.de.xlf @@ -9986,6 +9986,18 @@ Element 1 -> Element 1.2 Bauteil + + + project.bom.assembly + Baugruppe + + + + + project.bom.partOrAssembly + Auswahl + + project.bom.add_entry @@ -10106,6 +10118,42 @@ Element 1 -> Element 1.2 Archiviert + + + assembly.edit.status + Status + + + + + assembly.status.draft + Entwurf + + + + + assembly.status.planning + In Planung + + + + + assembly.status.in_production + In Produktion + + + + + assembly.status.finished + Abgeschlossen + + + + + assembly.status.archived + Archiviert + + part.new_build_part.error.build_part_already_exists @@ -10382,6 +10430,12 @@ Element 1 -> Element 1.2 vorhanden + + + project.builds.no_stock + kein Lager angegeben + + project.builds.needed @@ -10454,6 +10508,12 @@ Element 1 -> Element 1.2 Ziel-Bestand + + + project.build.builds_part_lot_label + %name% (%quantity% benötigt) + + project.builds.number_of_builds @@ -13482,6 +13542,622 @@ Bitte beachten Sie, dass Sie sich nicht als deaktivierter Benutzer ausgeben kön Baugruppen + + + assembly.edit + Bearbeite Baugruppe + + + + + assembly.new + Neue Baugruppe + + + + + assembly.edit.associated_build_part + Verknüpftes Bauteil + + + + + assembly.edit.associated_build_part.add + Bauteil hinzufügen + + + + + assembly.edit.associated_build.hint + Dieses Bauteil repräsentiert die gebauten Instanzen der Baugruppe. Anzugeben, sofern gebaute Instanzen benötigt werden. Wenn nein, werden die Stückzahlen bzgl. der Baugruppe erst beim Build des jeweiligen Projektes herangezogen. + + + + + assembly.edit.bom.import_bom + Bauteile importieren + + + + + log.database_updated.failed + __log.database_updated.failed + + + + + log.database_updated.old_version + __log.database_updated.old_version + + + + + log.database_updated.new_version + __log.database_updated.new_version + + + + + tree.tools.edit.assemblies + Baugruppen + + + + + assembly.bom_import.flash.success + %count% Part Einträge erfolgreich in Baugruppe importiert. + + + + + assembly.bom_import.flash.invalid_entries + Validierungsfehler! Bitte überprüfen Sie die importierte Datei! + + + + + assembly.bom_import.flash.invalid_file + Datei konnte nicht importiert werden. Überprüfen Sie, dass Sie den richtigen Dateityp gewählt haben. Fehlermeldung: %message% + + + + + assembly.bom.quantity + Menge + + + + + assembly.bom.mountnames + Bestückungsnamen + + + + + assembly.bom.instockAmount + Bestand im Lager + + + + + assembly.info.title + Baugruppen-Info + + + + + assembly.info.info.label + Info + + + + + assembly.info.sub_assemblies.label + Untergruppe + + + + + assembly.info.builds.label + Bau + + + + + assembly.info.bom_add_parts + Bauteile hinzufügen + + + + + assembly.builds.check_assembly_status + "%assembly_status%". Sie sollten überprüfen, ob sie die Baugruppe mit diesem Status wirklich bauen wollen!]]> + + + + + assembly.builds.build_not_possible + Bau nicht möglich: Nicht genügend Bauteile vorhanden + + + + + assembly.builds.following_bom_entries_miss_instock + Es sind nicht genügend Bauteile auf Lager, um dieses Projekt %number_of_builds% mal zu bauen. Von folgenden Bauteilen ist nicht genügend auf Lager. + + + + + assembly.builds.build_possible + Bau möglich + + + + + assembly.builds.number_of_builds_possible + %max_builds% Exemplare dieser Baugruppe zu bauen.]]> + + + + + assembly.builds.number_of_builds + Zu bauende Anzahl + + + + + assembly.build.btn_build + Bauen + + + + + assembly.builds.no_stocked_builds + Anzahl gelagerter gebauter Instanzen + + + + + assembly.info.bom_entries_count + Bauteile + + + + + assembly.info.sub_assemblies_count + Untergruppen + + + + + assembly.builds.stocked + vorhanden + + + + + assembly.builds.needed + benötigt + + + + + assembly.add_parts_to_assembly + Bauteile zur Baugruppe hinzufügen + + + + + assembly.bom.name + Name + + + + + assembly.bom.comment + Notizen + + + + + assembly.builds.following_bom_entries_miss_instock_n + Es sind nicht genügend Bauteile auf Lager, um diese Baugruppe %number_of_builds% mal zu bauen. Von folgenden Bauteilen ist nicht genügend auf Lager: + + + + + assembly.build.help + Wählen Sie aus, aus welchen Beständen die zum Bau notwendigen Bauteile genommen werden sollen (und in welcher Anzahl). Setzen Sie den Haken für jeden Part Eintrag, wenn sie die Bauteile entnommen haben, oder nutzen Sie die oberste Checkbox, um alle Haken auf einmal zu setzen. + + + + + assembly.build.required_qty + Benötigte Anzahl + + + + + assembly.import_bom + Importiere Parts für Baugruppe + + + + + assembly.bom.part + Bauteil + + + + + assembly.bom.add_entry + Eintrag hinzufügen + + + + + assembly.bom.price + Preis + + + + + assembly.build.dont_check_quantity + Mengen nicht überprüfen + + + + + assembly.build.dont_check_quantity.help + Wenn diese Option gewählt wird, werden die gewählten Mengen aus dem Lager entfernt, egal ob mehr oder weniger Bauteile sind, als für den Bau der Baugruppe eigentlich benötigt werden. + + + + + assembly.build.add_builds_to_builds_part + Gebaute Instanzen zum Bauteil der Baugruppe hinzufügen + + + + + assembly.bom_import.type + Typ + + + + + assembly.bom_import.type.json + JSON für eine Baugruppe + + + + + assembly.bom_import.type.kicad_pcbnew + CSV (KiCAD Pcbnew BOM) + + + + + assembly.bom_import.clear_existing_bom + Lösche existierende Bauteil-Einträge vor dem Import + + + + + assembly.bom_import.clear_existing_bom.help + Wenn diese Option ausgewählt ist, werden alle bereits in der Baugruppe existierenden Bauteile gelöscht und mit den importierten Bauteildaten überschrieben. + + + + + assembly.import_bom.template.header.json + Import-Vorlage JSON für eine Baugruppe + + + + + assembly.import_bom.template.header.kicad_pcbnew + Import-Vorlage CSV (KiCAD Pcbnew BOM) für eine Baugruppe + + + + + assembly.bom_import.template.entry.name + Name des Bauteils in der Baugruppe + + + + + assembly.bom_import.template.entry.part.mpnr + Eindeutige Produktnummer innerhalb des Herstellers + + + + + assembly.bom_import.template.entry.part.ipn + Eideutige IPN des Bauteils + + + + + assembly.bom_import.template.entry.part.name + Eindeutiger Name des Bauteils + + + + + assembly.bom_import.template.entry.part.manufacturer.name + Eindeutiger Name des Herstellers + + + + + assembly.bom_import.template.entry.part.category.name + Eindeutiger Name der Kategorie + + + + + assembly.bom_import.template.json.table + + + + + Feld + Bedingung + Datentyp + Beschreibung + + + + + quantity + Pflichtfeld + Gleitkommazahl (Float) + Muss gegeben sein und enthält einen Gleitkommawert (Float), der größer als 0.0 ist. + + + name + Optional + String + Falls vorhanden, muss es ein nicht-leerer String sein. + + + part + Optional + Objekt/Array + + Falls angegeben, muss es ein Objekt/Array sein und mindestens eines der Felder ausgefüllt sein: +
    +
  • part.id
  • +
  • part.name
  • +
+ + + + part.id + Optional + Ganzzahl (Integer) + Ganzzahl (Integer) > 0. Entspricht der Part-DB internen numerischen ID des Bauteils. + + + part.name + Optional + String + Nicht-leerer String, falls keine part.mpnr- bzw. part.ipn-Angabe gegeben ist. + + + part.mpnr + Optional + String + Nicht-leerer String, falls keine part.name- bzw. part-ipn-Angabe gegeben ist. + + + part.ipn + Optional + String + Nicht-leerer String, falls keine part.name- bzw. part.mpnr-Angabe gegeben ist. + + + part.description + Optional + String oder null + Falls vorhanden, muss es ein nicht-leerer String sein oder null. + + + part.manufacturer + Optional + Objekt/Array + + Falls vorhanden, muss es ein Objekt/Array sein und mindestens eines der Felder ausgefüllt sein: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + Optional + Ganzzahl (Integer) + Ganzzahl (Integer) > 0. Entspricht der internen numerischen ID des Herstellers. + + + manufacturer.name + Optional + String + Nicht-leerer String, falls keine manufacturer.id-Angabe gegeben ist. + + + part.category + Optional + Objekt/Array + + Falls vorhanden, muss es ein Objekt/Array sein und mindestens eines der Felder ausgefüllt sein: +
    +
  • category.id
  • +
  • category.name
  • +
+ + + + category.id + Optional + Ganzzahl (Integer) + Ganzzahl (Integer) > 0. Entspricht der internen numerischen ID der Kategorie des Bauteils. + + + category.name + Optional + String + Nicht-leerer String, falls keine category.id-Angabe gegeben ist. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.exptected_columns + Erwartete Spalten: + + + + + assembly.bom_import.template.kicad_pcbnew.exptected_columns.note + + Hinweis: Es findet keine Zuordnung zu konkreten Bauteilen aus der Kategorie-Verwaltung statt.

+ ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.table + + + + + Feld + Bedingung + Datentyp + Beschreibung + + + + + Id + Optional + Ganzzahl (Integer) + Offene Angabe. Eine eindeutige Identifikationsnummer für jedes Bauteil. + + + Designator + Optional + String + Offene Angabe. Ein eindeutiger Referenzbezeichner des Bauteils auf der Leiterplatte, z.B. „R1“ für Widerstand 1. Wird für den Bestückungsnamen des Bauteil-Eintrags innerhalb der Bauteilgruppe verwendet. + + + Package + Optional + String + Offene Angabe. Das Gehäuse oder die Bauform des Bauteils, z.B. „0805“ für SMD-Widerstände. + + + Quantity + Pflichtfeld + Ganzzahl (Integer) + Anzahl der identischen Bauteile, die benötigt werden, um eine Instanz der Baugruppe zu erstellen. + + + Designation + Pflichtfeld + String + Beschreibung oder Funktion des Bauteils, z.B. Widerstandswert „10kΩ“ oder Kondensatorwert „100nF“. Wird für den Namen des BOM-Eintrags verwendet. + + + Supplier and ref + Optional + String + Offene Angabe. Kann z.B. Distributor spezifischen Wert enthalten. + + + + ]]> + + + + + + typeahead.parts.part.name + %name% (Bauteil) + + + + + typeahead.parts.assembly.name + %name% (Baugruppe) + + + + + projects.build.form.part + Bauteil "%name%" + + + + + projects.build.form.assembly + Baugruppe "%name%" + + + + + projects.build.form.assembly.bom.entry + %name% (%quantity% benötigt) + + + + + projects.build.form.assembly.bom.entry.no.stock + nicht auf Lager + + + + + assembly.label + Baugruppe + + + + + assembly.caption + Baugruppe + + + + + perm.assemblies + Baugruppen + + + + + assembly_bom_entry.label + Bauteile + + + + + assembly.labelp + Baugruppen + + assembly.referencedAssembly.labelp diff --git a/translations/messages.el.xlf b/translations/messages.el.xlf index ccbed9fb..e3f3bcf7 100644 --- a/translations/messages.el.xlf +++ b/translations/messages.el.xlf @@ -2614,5 +2614,693 @@ Δημιουργήστε πρώτα ένα εξάρτημα και αντιστοιχίστε το σε μια κατηγορία: με τις υπάρχουσες κατηγορίες και τα δικά τους προθέματα IPN, η ονομασία IPN για το εξάρτημα μπορεί να προταθεί αυτόματα + + + part.table.name.value.for_part + %value% (Μέρος) + + + + + part.table.name.value.for_assembly + %value% (Συναρμολόγηση) + + + + + project.bom.assembly + Συναρμολόγηση + + + + + project.bom.partOrAssembly + Επιλογή + + + + + assembly.edit.status + Κατάσταση + + + + + assembly.status.draft + Προσχέδιο + + + + + assembly.status.planning + Υπό σχεδιασμό + + + + + assembly.status.in_production + Σε παραγωγή + + + + + assembly.status.finished + Ολοκληρώθηκε + + + + + assembly.status.archived + Αρχειοθετήθηκε + + + + + project.builds.no_stock + δεν έχει καθοριστεί απόθεμα + + + + + project.build.builds_part_lot_label + %name% (%quantity% απαιτείται) + + + + + assembly.label + Σύνολο + + + + + assembly.caption + Σύνολο + + + + + perm.assemblies + Συναρμολογήσεις + + + + + assembly_bom_entry.label + Μέρη + + + + + assembly.labelp + Συναρμολογήσεις + + + + + assembly.edit + Επεξεργασία συνόλου + + + + + assembly.new + Νέο σύνολο + + + + + assembly.edit.associated_build_part + Σχετικό μέρος + + + + + assembly.edit.associated_build_part.add + Προσθήκη μέρους + + + + + assembly.edit.associated_build.hint + Αυτό το μέρος αντιπροσωπεύει τις κατασκευασμένες εκδόσεις του συνόλου. Καταχωρίστε το εάν απαιτούνται κατασκευασμένες εκδόσεις. Εάν όχι, οι ποσότητες θα χρησιμοποιηθούν μόνο κατά την κατασκευή του εκάστοτε έργου. + + + + + assembly.edit.bom.import_bom + Εισαγωγή μερών + + + + + log.database_updated.failed + __log.database_updated.failed + + + + + log.database_updated.old_version + __log.database_updated.old_version + + + + + log.database_updated.new_version + __log.database_updated.new_version + + + + + tree.tools.edit.assemblies + Συναρμολογήσεις + + + + + assembly.bom_import.flash.success + %count% εγγραφές εξαρτημάτων εισήχθησαν με επιτυχία στο σύνολο. + + + + + assembly.bom_import.flash.invalid_entries + Σφάλμα επικύρωσης! Ελέγξτε το εισαγόμενο αρχείο! + + + + + assembly.bom_import.flash.invalid_file + Το αρχείο δεν μπόρεσε να εισαχθεί. Ελέγξτε ότι έχετε επιλέξει τον σωστό τύπο αρχείου. Μήνυμα σφάλματος: %message% + + + + + assembly.bom.quantity + Ποσότητα + + + + + assembly.bom.mountnames + Ονόματα συναρμολόγησης + + + + + assembly.bom.instockAmount + Ποσότητα σε απόθεμα + + + + + assembly.info.title + Πληροφορίες συναρμολόγησης + + + + + assembly.info.info.label + Πληροφορίες + + + + + assembly.info.sub_assemblies.label + Υποομάδες + + + + + assembly.info.builds.label + Κατασκευές + + + + + assembly.info.bom_add_parts + Προσθήκη εξαρτημάτων + + + + + assembly.builds.check_assembly_status + «%assembly_status%». Ελέγξτε εάν θέλετε πραγματικά να κατασκευάσετε τη συναρμολόγηση με αυτήν την κατάσταση!]]> + + + + + assembly.builds.build_not_possible + Η κατασκευή δεν είναι δυνατή: Δεν υπάρχουν αρκετά διαθέσιμα εξαρτήματα + + + + + assembly.builds.following_bom_entries_miss_instock + Δεν υπάρχουν αρκετά εξαρτήματα σε απόθεμα για να κατασκευαστεί αυτό το έργο %number_of_builds% φορές. Λείπουν τα ακόλουθα εξαρτήματα: + + + + + assembly.builds.build_possible + Κατασκευή δυνατή + + + + + assembly.builds.number_of_builds_possible + %max_builds% μονάδες αυτής της συναρμολόγησης.]]> + + + + + assembly.builds.number_of_builds + Αριθμός κατασκευών + + + + + assembly.build.btn_build + Κατασκευή + + + + + assembly.builds.no_stocked_builds + Αποθηκευμένα κατασκευασμένα κομμάτια + + + + + assembly.info.bom_entries_count + Εξαρτήματα + + + + + assembly.info.sub_assemblies_count + Υποομάδες + + + + + assembly.builds.stocked + σε απόθεμα + + + + + assembly.builds.needed + απαιτούμενο + + + + + assembly.add_parts_to_assembly + Προσθήκη εξαρτημάτων στη συναρμολόγηση + + + + + assembly.bom.name + Όνομα + + + + + assembly.bom.comment + Σχόλια + + + + + assembly.builds.following_bom_entries_miss_instock_n + Δεν υπάρχουν αρκετά εξαρτήματα σε απόθεμα για να κατασκευαστεί αυτή η συναρμολόγηση %number_of_builds% φορές. Λείπουν τα ακόλουθα εξαρτήματα: + + + + + assembly.build.help + Επιλέξτε από ποια αποθέματα θα αφαιρεθούν τα αναγκαία για την κατασκευή εξαρτήματα (και σε ποια ποσότητα). Σημειώστε το πλαίσιο επιλογής για κάθε εξάρτημα όταν αφαιρέσετε τα εξαρτήματα ή χρησιμοποιήστε το ανώτερο πλαίσιο επιλογής για να τα ελέγξετε όλα ταυτόχρονα. + + + + + assembly.build.required_qty + Απαιτούμενη ποσότητα + + + + + assembly.import_bom + Εισαγωγή εξαρτημάτων συναρμολόγησης + + + + + assembly.bom.part + Εξάρτημα + + + + + assembly.bom.add_entry + Προσθήκη καταχώρησης + + + + + assembly.bom.price + Τιμή + + + + + assembly.build.dont_check_quantity + Μην ελέγχετε την ποσότητα + + + + + assembly.build.dont_check_quantity.help + Εάν επιλεγεί αυτή η επιλογή, οι επιλεγμένες ποσότητες θα αφαιρεθούν από το απόθεμα ανεξάρτητα από το αν είναι περισσότερο ή λιγότερο από το απαιτούμενο για την κατασκευή της συναρμολόγησης. + + + + + assembly.build.add_builds_to_builds_part + Προσθήκη κατασκευασμένων κομματιών στο τμήμα συναρμολόγησης + + + + + assembly.bom_import.type + Τύπος + + + + + assembly.bom_import.type.json + JSON για συναρμολόγηση + + + + + assembly.bom_import.type.kicad_pcbnew + CSV (KiCAD Pcbnew BOM) + + + + + assembly.bom_import.clear_existing_bom + Διαγραφή υπαρχόντων εξαρτημάτων πριν από την εισαγωγή + + + + + assembly.bom_import.clear_existing_bom.help + Εάν επιλεγεί αυτή η επιλογή, όλα τα ήδη υπάρχοντα εξαρτήματα στη συναρμολόγηση θα διαγραφούν και θα αντικατασταθούν με τα δεδομένα εξαρτημάτων που εισάγονται. + + + + + assembly.import_bom.template.header.json + Πρότυπο εισαγωγής JSON για συναρμολόγηση + + + + + assembly.import_bom.template.header.kicad_pcbnew + Πρότυπο εισαγωγής CSV (KiCAD Pcbnew BOM) για συναρμολόγηση + + + + + assembly.bom_import.template.entry.name + Όνομα του εξαρτήματος στη συναρμολόγηση + + + + + assembly.bom_import.template.entry.part.mpnr + Μοναδικός αριθμός προϊόντος από τον κατασκευαστή + + + + + assembly.bom_import.template.entry.part.ipn + Μοναδικός IPN του εξαρτήματος + + + + + assembly.bom_import.template.entry.part.name + Μοναδικό όνομα εξαρτήματος + + + + + assembly.bom_import.template.entry.part.manufacturer.name + Μοναδικό όνομα κατασκευαστή + + + + + assembly.bom_import.template.entry.part.category.name + Μοναδικό όνομα κατηγορίας + + + + + assembly.bom_import.template.json.table + + + + + Πεδίο + Προϋπόθεση + Τύπος Δεδομένων + Περιγραφή + + + + + quantity + Υποχρεωτικό πεδίο + Αριθμός κινητής υποδιαστολής (Float) + Πρέπει να παρέχεται και να περιέχει τιμή κινητής υποδιαστολής (Float) μεγαλύτερη από 0.0. + + + name + Προαιρετικό + Κείμενο (String) + Εάν υπάρχει, πρέπει να είναι μη κενό κείμενο. + + + part + Προαιρετικό + Αντικείμενο/Πίνακας + + Εάν παρέχεται, πρέπει να είναι αντικείμενο/πίνακας και τουλάχιστον ένα από τα πεδία του να είναι συμπληρωμένο: +
    +
  • part.id
  • +
  • part.name
  • +
+ + + + part.id + Προαιρετικό + Ακέραιος αριθμός (Integer) + Ακέραιος (Integer) > 0. Αντιστοιχεί στην εσωτερική αριθμητική ταυτότητα (ID) του εξαρτήματος στη βάση δεδομένων. + + + part.name + Προαιρετικό + Κείμενο (String) + Μη κενό κείμενο, εάν δεν παρέχονται οι ενδείξεις part.mpnr ή part.ipn. + + + part.mpnr + Προαιρετικό + Κείμενο (String) + Μη κενό κείμενο, εάν δεν παρέχονται οι ενδείξεις part.name ή part.ipn. + + + part.ipn + Προαιρετικό + Κείμενο (String) + Μη κενό κείμενο, εάν δεν παρέχονται οι ενδείξεις part.name ή part.mpnr. + + + part.description + Προαιρετικό + Κείμενο ή null + Εάν υπάρχει, πρέπει να είναι μη κενό κείμενο, ή null. + + + part.manufacturer + Προαιρετικό + Αντικείμενο/Πίνακας + + Εάν υπάρχει, πρέπει να είναι αντικείμενο/πίνακας και τουλάχιστον ένα από τα πεδία του να είναι συμπληρωμένο: +
    +
  • manufacturer.id
  • +
  • manufacturer.name
  • +
+ + + + manufacturer.id + Προαιρετικό + Ακέραιος αριθμός (Integer) + Ακέραιος (Integer) > 0. Αντιστοιχεί στην εσωτερική αριθμητική ταυτότητα (ID) του κατασκευαστή. + + + manufacturer.name + Προαιρετικό + Κείμενο (String) + Μη κενό κείμενο, εάν δεν παρέχεται η ένδειξη manufacturer.id. + + + part.category + Προαιρετικό + Αντικείμενο/Πίνακας + + Εάν υπάρχει, πρέπει να είναι αντικείμενο/πίνακας και τουλάχιστον ένα από τα πεδία του να είναι συμπληρωμένο: +
    +
  • category.id
  • +
  • category.name
  • +
+ + + + category.id + Προαιρετικό + Ακέραιος αριθμός (Integer) + Ακέραιος (Integer) > 0. Αντιστοιχεί στην εσωτερική αριθμητική ταυτότητα (ID) της κατηγορίας του εξαρτήματος. + + + category.name + Προαιρετικό + Κείμενο (String) + Μη κενό κείμενο, εάν δεν παρέχεται η ένδειξη category.id. + + + + ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.exptected_columns + Αναμενόμενες στήλες: + + + + + assembly.bom_import.template.kicad_pcbnew.exptected_columns.note + + Σημείωση: Δεν πραγματοποιείται αντιστοίχιση με συγκεκριμένα εξαρτήματα από τη διαχείριση κατηγοριών.

+ ]]> +
+
+
+ + + assembly.bom_import.template.kicad_pcbnew.table + + + + + Πεδίο + Εκπλήρωση + Τύπος δεδομένων + Περιγραφή + + + + + Id + Προαιρετικό + Ακέραιος αριθμός (Integer) + Ελεύθερη καταχώρηση. Μοναδικός αριθμός ταυτοποίησης για κάθε εξάρτημα. + + + Σχεδιαστής + Προαιρετικό + Συμβολοσειρά (String) + Ελεύθερη καταχώρηση. Μοναδικός αναγνωριστικός δείκτης του εξαρτήματος στην πλακέτα κυκλώματος, π.χ. "R1" για την αντίσταση 1. Χρησιμοποιείται για το όνομα του εξαρτήματος στο πλαίσιο της ομάδας εξαρτημάτων. + + + Συσκευασία + Προαιρετικό + Συμβολοσειρά (String) + Ελεύθερη καταχώρηση. Ο τύπος ή η μορφή του εξαρτήματος, π.χ. "0805" για αντιστάσεις SMD. + + + Ποσότητα + Υποχρεωτικό + Ακέραιος αριθμός (Integer) + Ο αριθμός των πανομοιότυπων εξαρτημάτων που απαιτούνται για τη δημιουργία μίας μονάδας του συνόλου. + + + Ορισμός + Υποχρεωτικό + Συμβολοσειρά (String) + Περιγραφή ή λειτουργία του εξαρτήματος, π.χ. αντίσταση "10kΩ" ή χωρητικότητα "100nF". Χρησιμοποιείται για το όνομα της εγγραφής στο BOM. + + + Προμηθευτής και παραπομπή + Προαιρετικό + Συμβολοσειρά (String) + Ελεύθερη καταχώρηση. Μπορεί να περιλαμβάνει, π.χ., ειδική τιμή από διανομέα. + + + + ]]> + + + + + + typeahead.parts.part.name + %name% (Εξάρτημα) + + + + + typeahead.parts.assembly.name + %name% (Συναρμολόγηση) + + + + + projects.build.form.part + Εξάρτημα "%name%" + + + + + projects.build.form.assembly + Συναρμολόγηση "%name%" + + + + + projects.build.form.assembly.bom.entry + %name% (%quantity% απαιτείται) + + + + + projects.build.form.assembly.bom.entry.no.stock + δεν υπάρχει στο απόθεμα + + diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf index 4ff8eddd..22e4a4cc 100644 --- a/translations/messages.en.xlf +++ b/translations/messages.en.xlf @@ -4831,6 +4831,18 @@ If you have done this incorrectly or if a computer is no longer trusted, you can %value% (Project) + + + part.table.name.value.for_part + %value% (Part) + + + + + part.table.name.value.for_assembly + %value% (Assembly) + + Part-DB1\src\DataTables\PartsDataTable.php:178 @@ -9987,6 +9999,18 @@ Element 1 -> Element 1.2 Part + + + project.bom.assembly + Assembly + + + + + project.bom.partOrAssembly + Selection + + project.bom.add_entry @@ -10383,6 +10407,12 @@ Element 1 -> Element 1.2 stocked + + + project.builds.no_stock + no stock specified + + project.builds.needed @@ -10455,6 +10485,12 @@ Element 1 -> Element 1.2 Target lot + + + project.build.builds_part_lot_label + %name% (%quantity% needed) + + project.builds.number_of_builds diff --git a/translations/messages.es.xlf b/translations/messages.es.xlf index 999fd71a..66e93680 100644 --- a/translations/messages.es.xlf +++ b/translations/messages.es.xlf @@ -9930,6 +9930,18 @@ Elemento 3 Componente + + + project.bom.assembly + Baugruppe + + + + + project.bom.partOrAssembly + Auswahl + + project.bom.add_entry @@ -10326,6 +10338,12 @@ Elemento 3 Almacenado + + + project.builds.no_stock + no se ha especificado stock + + project.builds.needed @@ -10398,6 +10416,12 @@ Elemento 3 Lote objetivo + + + project.build.builds_part_lot_label + %name% (se requiere %quantity%) + + project.builds.number_of_builds diff --git a/translations/messages.it.xlf b/translations/messages.it.xlf index 951a1bd3..68125368 100644 --- a/translations/messages.it.xlf +++ b/translations/messages.it.xlf @@ -9932,6 +9932,18 @@ Element 3 Componente + + + project.bom.assembly + Assemblaggio + + + + + project.bom.partOrAssembly + Selezione + + project.bom.add_entry @@ -10328,6 +10340,12 @@ Element 3 a magazzino + + + project.builds.no_stock + nessuna scorta specificata + + project.builds.needed @@ -10400,6 +10418,12 @@ Element 3 Lotto target + + + project.build.builds_part_lot_label + %name% (%quantity% richiesti) + + project.builds.number_of_builds diff --git a/translations/messages.ja.xlf b/translations/messages.ja.xlf index 101afd62..fb772306 100644 --- a/translations/messages.ja.xlf +++ b/translations/messages.ja.xlf @@ -8960,6 +8960,18 @@ Exampletown Part-DBについての質問は、<a href="%href%" class="link-external" target="_blank">GitHub</a> にスレッドがあります。 + + + project.bom.assembly + アセンブリ + + + + + project.bom.partOrAssembly + 選択 + + assembly.edit.status @@ -8996,6 +9008,18 @@ Exampletown アーカイブ済み + + + project.builds.no_stock + nessuna scorta specificata + + + + + project.build.builds_part_lot_label + %name% (必要数: %quantity%) + + assembly.label diff --git a/translations/messages.pl.xlf b/translations/messages.pl.xlf index d9d4eac2..5654d1de 100644 --- a/translations/messages.pl.xlf +++ b/translations/messages.pl.xlf @@ -10331,6 +10331,12 @@ Element 3 dostępny + + + project.builds.no_stock + brak podanego stanu magazynowego + + project.builds.needed @@ -10403,6 +10409,12 @@ Element 3 Partia docelowa + + + project.build.builds_part_lot_label + %name% (%quantity% wymagane) + + project.builds.number_of_builds diff --git a/translations/messages.ru.xlf b/translations/messages.ru.xlf index 3589e4e1..326044b8 100644 --- a/translations/messages.ru.xlf +++ b/translations/messages.ru.xlf @@ -743,7 +743,7 @@ user.edit.tfa.disable_tfa_message - Это выключит <b>все активные двухфакторной способы аутентификации пользователя</b>и удалит <b>резервные коды</b>! + Это выключит <b>все активные двухфакторной способы аутентификации пользователя</b>и удалит <b>резервные коды</b>! <br> Пользователь должен будет снова настроить все методы двухфакторной аутентификации и распечатать новые резервные коды! <br><br> <b>Делайте это только в том случае, если вы абсолютно уверены в личности пользователя (обращающегося за помощью), в противном случае учетная запись может быть взломана злоумышленником!</b> @@ -3812,7 +3812,7 @@ tfa_backup.reset_codes.confirm_message - Это удалит все предыдущие коды и создаст набор новых. Это не может быть отменено. + Это удалит все предыдущие коды и создаст набор новых. Это не может быть отменено. Не забудьте распечатать новы кода и хранить их в безопасном месте! @@ -9939,6 +9939,18 @@ Компонент + + + project.bom.assembly + Сборка + + + + + project.bom.partOrAssembly + Выбор + + project.bom.add_entry @@ -10335,6 +10347,12 @@ запасено + + + project.builds.no_stock + склад не указан + + project.builds.needed @@ -10407,6 +10425,12 @@ Целевой лот + + + project.build.builds_part_lot_label + %name% (требуется: %quantity%) + + project.builds.number_of_builds diff --git a/translations/messages.zh.xlf b/translations/messages.zh.xlf index a3e44de6..aa730c08 100644 --- a/translations/messages.zh.xlf +++ b/translations/messages.zh.xlf @@ -9938,6 +9938,18 @@ Element 3 部件 + + + project.bom.assembly + 装配 + + + + + project.bom.partOrAssembly + 选择 + + project.bom.add_entry @@ -10334,6 +10346,12 @@ Element 3 在库 + + + project.builds.no_stock + 未指定库存 + + project.builds.needed @@ -10406,6 +10424,12 @@ Element 3 目标批次 + + + project.build.builds_part_lot_label + %name% (需求数量: %quantity%) + + project.builds.number_of_builds diff --git a/translations/validators.cs.xlf b/translations/validators.cs.xlf index 245e61e3..5b899d98 100644 --- a/translations/validators.cs.xlf +++ b/translations/validators.cs.xlf @@ -251,6 +251,12 @@ Musíte vybrat díl pro položku BOM dílu nebo nastavit název pro položku BOM bez dílu. + + + validator.project.bom_entry.only_part_or_assembly_allowed + Je povoleno vybrat pouze jednu součástku nebo sestavu. Upravit prosím svůj výběr! + + project.bom_entry.name_already_in_bom diff --git a/translations/validators.da.xlf b/translations/validators.da.xlf index f30dd211..bf4125fe 100644 --- a/translations/validators.da.xlf +++ b/translations/validators.da.xlf @@ -251,6 +251,12 @@ Du skal vælge en komponent eller angive et navn til en ikke-komponent styklistepost! + + + validator.project.bom_entry.only_part_or_assembly_allowed + Det er kun tilladt at vælge én del eller en samling. Venligst tilpas dit valg! + + project.bom_entry.name_already_in_bom diff --git a/translations/validators.de.xlf b/translations/validators.de.xlf index 8e6d7f02..fec52c8e 100644 --- a/translations/validators.de.xlf +++ b/translations/validators.de.xlf @@ -251,6 +251,12 @@ Sie müssen ein Bauteil bzw. eine Baugruppe auswählen, oder einen Namen für ein nicht-Bauteil BOM-Eintrag setzen! + + + validator.project.bom_entry.only_part_or_assembly_allowed + Es darf nur ein Bauteil oder eine Baugruppe ausgewählt werden. Bitte passen Sie Ihre Auswahl an! + + project.bom_entry.name_already_in_bom diff --git a/translations/validators.en.xlf b/translations/validators.en.xlf index 53ad4cde..658a47e1 100644 --- a/translations/validators.en.xlf +++ b/translations/validators.en.xlf @@ -251,6 +251,12 @@ You have to select a part or assembly, or set a name for a non-component Bom entry! + + + validator.project.bom_entry.only_part_or_assembly_allowed + Only one part or assembly may be selected. Please modify your selection! + + project.bom_entry.name_already_in_bom diff --git a/translations/validators.hr.xlf b/translations/validators.hr.xlf index 485cb0e2..c14b86f1 100644 --- a/translations/validators.hr.xlf +++ b/translations/validators.hr.xlf @@ -251,6 +251,12 @@ Morate odabrati dio za unos u BOM ili postaviti naziv za unos koji nije dio. + + + validator.project.bom_entry.only_part_or_assembly_allowed + Dozvoljeno je odabrati samo jednu komponentu ili sklop. Molimo prilagodite svoj odabir! + + project.bom_entry.name_already_in_bom diff --git a/translations/validators.it.xlf b/translations/validators.it.xlf index 74d3969f..7f88537c 100644 --- a/translations/validators.it.xlf +++ b/translations/validators.it.xlf @@ -251,6 +251,12 @@ È necessario selezionare un componente o assegnare un nome ad una voce BOM che non indica un componente! + + + validator.project.bom_entry.only_part_or_assembly_allowed + È consentito selezionare solo una parte o un assieme. Si prega di modificare la selezione! + + project.bom_entry.name_already_in_bom diff --git a/translations/validators.pl.xlf b/translations/validators.pl.xlf index 9916178c..060de0e1 100644 --- a/translations/validators.pl.xlf +++ b/translations/validators.pl.xlf @@ -251,6 +251,12 @@ Należy wybrać część dla wpisu BOM części lub ustawić nazwę dla wpisu BOM niebędącego częścią. + + + validator.project.bom_entry.only_part_or_assembly_allowed + Można wybrać tylko jedną część lub zespół. Proszę dostosować swój wybór! + + project.bom_entry.name_already_in_bom diff --git a/translations/validators.ru.xlf b/translations/validators.ru.xlf index b8029e47..e4a3199f 100644 --- a/translations/validators.ru.xlf +++ b/translations/validators.ru.xlf @@ -251,6 +251,12 @@ Вам необходимо выбрать компонент или задать имя для BOM, не относящейся к компоненту! + + + validator.project.bom_entry.only_part_or_assembly_allowed + Можно выбрать только деталь или сборку. Пожалуйста, измените ваш выбор! + + project.bom_entry.name_already_in_bom diff --git a/translations/validators.zh.xlf b/translations/validators.zh.xlf index 6e4fc056..1844351e 100644 --- a/translations/validators.zh.xlf +++ b/translations/validators.zh.xlf @@ -251,6 +251,12 @@ 您必须为 BOM 条目选择部件,或为非部件 BOM 条目设置名称。 + + + validator.project.bom_entry.only_part_or_assembly_allowed + 只能选择一个零件或组件。请修改您的选择! + + project.bom_entry.name_already_in_bom