diff --git a/migrations/Version20250310160354.php b/migrations/Version20250310160354.php deleted file mode 100644 index 201e7e85..00000000 --- a/migrations/Version20250310160354.php +++ /dev/null @@ -1,188 +0,0 @@ -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 mySQLDown(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'); - } - - public function sqLiteUp(Schema $schema): void - { - $this->addSql(<<<'SQL' - CREATE TEMPORARY TABLE __temp__project_bom_entries AS - SELECT - id, - id_device, - id_part, - price_currency_id, - quantity, - mountnames, - name, - comment, - price, - last_modified, - datetime_added - FROM project_bom_entries - SQL); - - $this->addSql('DROP TABLE project_bom_entries'); - - $this->addSql(<<<'SQL' - CREATE TABLE project_bom_entries - ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - id_device INTEGER DEFAULT NULL, - id_assembly INTEGER DEFAULT NULL, - id_part INTEGER DEFAULT NULL, - price_currency_id INTEGER DEFAULT NULL, - quantity DOUBLE PRECISION NOT NULL, - mountnames CLOB NOT NULL, - name VARCHAR(255) DEFAULT NULL, - comment CLOB NOT NULL, - price NUMERIC(11, 5) DEFAULT NULL, - last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, - datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, - CONSTRAINT FK_1AA2DD312F180363 FOREIGN KEY (id_device) REFERENCES projects (id) NOT DEFERRABLE INITIALLY IMMEDIATE, - CONSTRAINT FK_1AA2DD314AD2039E FOREIGN KEY (id_assembly) REFERENCES assemblies (id) NOT DEFERRABLE INITIALLY IMMEDIATE, - CONSTRAINT FK_1AA2DD31C22F6CC4 FOREIGN KEY (id_part) REFERENCES "parts" (id) NOT DEFERRABLE INITIALLY IMMEDIATE, - CONSTRAINT FK_1AA2DD313FFDCD60 FOREIGN KEY (price_currency_id) REFERENCES currencies (id) NOT DEFERRABLE INITIALLY IMMEDIATE - ) - SQL); - - - $this->addSql(<<<'SQL' - INSERT INTO project_bom_entries ( - id, - id_device, - id_part, - price_currency_id, - quantity, - mountnames, - name, - comment, - price, - last_modified, - datetime_added - ) SELECT * FROM __temp__project_bom_entries - SQL); - $this->addSql('DROP TABLE __temp__project_bom_entries'); - - $this->addSql(<<<'SQL' - CREATE INDEX IDX_1AA2DD312F180363 ON project_bom_entries (id_device) - SQL); - $this->addSql(<<<'SQL' - CREATE INDEX IDX_1AA2DD31C22F6CC4 ON project_bom_entries (id_part) - SQL); - $this->addSql(<<<'SQL' - CREATE INDEX IDX_1AA2DD314AD2039E ON project_bom_entries (id_assembly) - SQL); - $this->addSql(<<<'SQL' - CREATE INDEX IDX_1AA2DD313FFDCD60 ON project_bom_entries (price_currency_id) - SQL); - } - - public function sqLiteDown(Schema $schema): void - { - $this->addSql(<<<'SQL' - CREATE TEMPORARY TABLE __temp__project_bom_entries AS - SELECT - id, - id_device, - id_part, - price_currency_id, - quantity, - mountnames, - name, - comment, - price, - last_modified, - datetime_added - FROM project_bom_entries - SQL); - - $this->addSql('DROP TABLE project_bom_entries'); - - $this->addSql(<<<'SQL' - CREATE TABLE project_bom_entries - ( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - id_device INTEGER DEFAULT NULL, - id_part INTEGER DEFAULT NULL, - price_currency_id INTEGER DEFAULT NULL, - quantity DOUBLE PRECISION NOT NULL, - mountnames CLOB NOT NULL, - name VARCHAR(255) DEFAULT NULL, - comment CLOB NOT NULL, - price NUMERIC(11, 5) DEFAULT NULL, - last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, - datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, - CONSTRAINT FK_1AA2DD312F180363 FOREIGN KEY (id_device) REFERENCES projects (id) NOT DEFERRABLE INITIALLY IMMEDIATE, - CONSTRAINT FK_1AA2DD31C22F6CC4 FOREIGN KEY (id_part) REFERENCES "parts" (id) NOT DEFERRABLE INITIALLY IMMEDIATE, - CONSTRAINT FK_1AA2DD313FFDCD60 FOREIGN KEY (price_currency_id) REFERENCES currencies (id) NOT DEFERRABLE INITIALLY IMMEDIATE - ) - SQL); - - $this->addSql(<<<'SQL' - INSERT INTO project_bom_entries ( - id, - id_device, - id_part, - price_currency_id, - quantity, - mountnames, - name, - comment, - price, - last_modified, - datetime_added - ) SELECT * FROM __temp__project_bom_entries - SQL); - - $this->addSql('DROP TABLE __temp__project_bom_entries'); - - $this->addSql(<<<'SQL' - CREATE INDEX IDX_1AA2DD312F180363 ON project_bom_entries (id_device) - SQL); - $this->addSql(<<<'SQL' - CREATE INDEX IDX_1AA2DD31C22F6CC4 ON project_bom_entries (id_part) - SQL); - $this->addSql(<<<'SQL' - CREATE INDEX IDX_1AA2DD313FFDCD60 ON project_bom_entries (price_currency_id) - SQL); - } - - public function postgreSQLUp(Schema $schema): void - { - //Not needed - } - - public function postgreSQLDown(Schema $schema): void - { - //Not needed - } -} diff --git a/src/DataTables/Helpers/AssemblyDataTableHelper.php b/src/DataTables/Helpers/AssemblyDataTableHelper.php deleted file mode 100644 index dda563ea..00000000 --- a/src/DataTables/Helpers/AssemblyDataTableHelper.php +++ /dev/null @@ -1,77 +0,0 @@ -. - */ - -namespace App\DataTables\Helpers; - -use App\Entity\AssemblySystem\Assembly; -use App\Entity\Attachments\Attachment; -use App\Services\Attachments\AssemblyPreviewGenerator; -use App\Services\Attachments\AttachmentURLGenerator; -use App\Services\EntityURLGenerator; - -/** - * A helper service which contains common code to render columns for assembly related tables - */ -class AssemblyDataTableHelper -{ - public function __construct( - private readonly EntityURLGenerator $entityURLGenerator, - private readonly AssemblyPreviewGenerator $previewGenerator, - private readonly AttachmentURLGenerator $attachmentURLGenerator - ) { - } - - public function renderName(Assembly $context): string - { - $icon = ''; - - return sprintf( - '%s%s', - $this->entityURLGenerator->infoURL($context), - $icon, - htmlspecialchars($context->getName()) - ); - } - - public function renderPicture(Assembly $context): string - { - $preview_attachment = $this->previewGenerator->getTablePreviewAttachment($context); - if (!$preview_attachment instanceof Attachment) { - return ''; - } - - $title = htmlspecialchars($preview_attachment->getName()); - if ($preview_attachment->getFilename()) { - $title .= ' ('.htmlspecialchars($preview_attachment->getFilename()).')'; - } - - return sprintf( - '%s', - 'Assembly image', - $this->attachmentURLGenerator->getThumbnailURL($preview_attachment), - $this->attachmentURLGenerator->getThumbnailURL($preview_attachment, 'thumbnail_md'), - 'hoverpic assembly-table-image', - $title - ); - } -} diff --git a/src/Entity/ProjectSystem/Project.php b/src/Entity/ProjectSystem/Project.php index 36a96377..a103d694 100644 --- a/src/Entity/ProjectSystem/Project.php +++ b/src/Entity/ProjectSystem/Project.php @@ -108,7 +108,6 @@ 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 f8caa5d5..b2a3b2e9 100644 --- a/src/Entity/ProjectSystem/ProjectBOMEntry.php +++ b/src/Entity/ProjectSystem/ProjectBOMEntry.php @@ -35,7 +35,6 @@ 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; @@ -105,10 +104,7 @@ 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.getAssembly() !== null or (this.getName() !== null and this.getName() != "")', - message: 'validator.project.bom_entry.part_or_assembly_needed' - )] + #[Assert\Expression('this.getPart() !== null or this.getName() !== null', message: 'validator.project.bom_entry.name_or_part_needed')] #[ORM\Column(type: Types::STRING, nullable: true)] #[Groups(['bom_entry:read', 'bom_entry:write', 'import', 'simple', 'extended', 'full'])] protected ?string $name = null; @@ -136,18 +132,6 @@ 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 */ @@ -240,16 +224,6 @@ 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. @@ -287,15 +261,6 @@ 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 { @@ -357,7 +322,6 @@ 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 c5dbe99f..61f72c41 100644 --- a/src/Form/ProjectSystem/ProjectAddPartsType.php +++ b/src/Form/ProjectSystem/ProjectAddPartsType.php @@ -59,7 +59,6 @@ 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/Form/Type/AssemblySelectType.php b/src/Form/Type/AssemblySelectType.php deleted file mode 100644 index 10e858f2..00000000 --- a/src/Form/Type/AssemblySelectType.php +++ /dev/null @@ -1,124 +0,0 @@ -addEventListener(FormEvents::PRE_SET_DATA, function (PreSetDataEvent $event) { - $form = $event->getForm(); - $config = $form->getConfig()->getOptions(); - $data = $event->getData() ?? []; - - $config['compound'] = false; - $config['choices'] = is_iterable($data) ? $data : [$data]; - $config['error_bubbling'] = true; - - $form->add('autocomplete', EntityType::class, $config); - }); - - //After form submit, we have to add the selected element as choice, otherwise the form will not accept this element - $builder->addEventListener(FormEvents::PRE_SUBMIT, function(FormEvent $event) { - $data = $event->getData(); - $form = $event->getForm(); - $options = $form->get('autocomplete')->getConfig()->getOptions(); - - - if (!isset($data['autocomplete']) || '' === $data['autocomplete'] || empty($data['autocomplete'])) { - $options['choices'] = []; - } else { - //Extract the ID from the submitted data - $id = $data['autocomplete']; - //Find the element in the database - $element = $this->em->find($options['class'], $id); - - //Add the element as choice - $options['choices'] = [$element]; - $options['error_bubbling'] = true; - $form->add('autocomplete', EntityType::class, $options); - } - }); - - $builder->setDataMapper($this); - } - - public function configureOptions(OptionsResolver $resolver): void - { - $resolver->setDefaults([ - 'class' => Assembly::class, - 'choice_label' => 'name', - 'compound' => true, - 'error_bubbling' => false, - ]); - - error_log($this->urlGenerator->generate('typeahead_assemblies', ['query' => '__QUERY__'])); - - $resolver->setDefaults([ - 'attr' => [ - 'data-controller' => 'elements--assembly-select', - 'data-autocomplete' => $this->urlGenerator->generate('typeahead_assemblies', ['query' => '__QUERY__']), - 'autocomplete' => 'off', - ], - ]); - - $resolver->setDefaults([ - //Prefill the selected choice with the needed data, so the user can see it without an additional Ajax request - 'choice_attr' => ChoiceList::attr($this, function (?Assembly $assembly) { - if($assembly instanceof Assembly) { - //Determine the picture to show: - $preview_attachment = $this->previewGenerator->getTablePreviewAttachment($assembly); - if ($preview_attachment instanceof Attachment) { - $preview_url = $this->attachmentURLGenerator->getThumbnailURL($preview_attachment, - 'thumbnail_sm'); - } else { - $preview_url = ''; - } - } - - return $assembly instanceof Assembly ? [ - 'data-description' => $assembly->getDescription() ? mb_strimwidth($assembly->getDescription(), 0, 127, '...') : '', - 'data-category' => '', - 'data-footprint' => '', - 'data-image' => $preview_url, - ] : []; - }) - ]); - } - - public function mapDataToForms($data, \Traversable $forms): void - { - $form = current(iterator_to_array($forms, false)); - $form->setData($data); - } - - public function mapFormsToData(\Traversable $forms, &$data): void - { - $form = current(iterator_to_array($forms, false)); - $data = $form->getData(); - } - -} diff --git a/src/Helpers/Projects/ProjectBuildRequest.php b/src/Helpers/Projects/ProjectBuildRequest.php index 3254565a..24bb5eb7 100644 --- a/src/Helpers/Projects/ProjectBuildRequest.php +++ b/src/Helpers/Projects/ProjectBuildRequest.php @@ -22,13 +22,10 @@ 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; /** @@ -82,7 +79,7 @@ final class ProjectBuildRequest //Completely reset the array $this->withdraw_amounts = []; - //Now create an array for each part BOM entry + //Now create an array for each BOM entry foreach ($this->getPartBomEntries() as $bom_entry) { $remaining_amount = $this->getNeededAmountForBOMEntry($bom_entry); foreach($this->getPartLotsForBOMEntry($bom_entry) as $lot) { @@ -91,21 +88,6 @@ 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()]); - } - } - } } /** @@ -248,77 +230,12 @@ final class ProjectBuildRequest { $this->ensureBOMEntryValid($projectBOMEntry); - if (!$projectBOMEntry->getPart() instanceof Part && !$projectBOMEntry->getAssembly() instanceof Assembly) { + if (!$projectBOMEntry->getPart() instanceof Part) { return null; } //Filter out all lots which have unknown instock - 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; + return $projectBOMEntry->getPart()->getPartLots()->filter(fn (PartLot $lot) => !$lot->isInstockUnknown())->toArray(); } /** @@ -349,15 +266,6 @@ 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/Repository/AssemblyRepository.php b/src/Repository/AssemblyRepository.php deleted file mode 100644 index 031e6e82..00000000 --- a/src/Repository/AssemblyRepository.php +++ /dev/null @@ -1,69 +0,0 @@ -. - */ - -declare(strict_types=1); - -/** - * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony). - * - * Copyright (C) 2019 - 2022 Jan Böhmer (https://github.com/jbtronics) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -namespace App\Repository; - -use App\Entity\AssemblySystem\Assembly; - -/** - * @template TEntityClass of Assembly - * @extends DBElementRepository - */ -class AssemblyRepository extends StructuralDBElementRepository -{ - /** - * @return Assembly[] - */ - public function autocompleteSearch(string $query, int $max_limits = 50): array - { - $qb = $this->createQueryBuilder('assembly'); - $qb->select('assembly') - ->where('ILIKE(assembly.name, :query) = TRUE') - ->orWhere('ILIKE(assembly.description, :query) = TRUE'); - - $qb->setParameter('query', '%'.$query.'%'); - - $qb->setMaxResults($max_limits); - $qb->orderBy('NATSORT(assembly.name)', 'ASC'); - - return $qb->getQuery()->getResult(); - } -} \ No newline at end of file diff --git a/src/Services/Attachments/AssemblyPreviewGenerator.php b/src/Services/Attachments/AssemblyPreviewGenerator.php deleted file mode 100644 index 9ecbbd07..00000000 --- a/src/Services/Attachments/AssemblyPreviewGenerator.php +++ /dev/null @@ -1,93 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace App\Services\Attachments; - -use App\Entity\AssemblySystem\Assembly; -use App\Entity\Attachments\Attachment; - -class AssemblyPreviewGenerator -{ - public function __construct(protected AttachmentManager $attachmentHelper) - { - } - - /** - * Returns a list of attachments that can be used for previewing the assembly ordered by priority. - * - * @param Assembly $assembly the assembly for which the attachments should be determined - * - * @return (Attachment|null)[] - * - * @psalm-return list - */ - public function getPreviewAttachments(Assembly $assembly): array - { - $list = []; - - //Master attachment has top priority - $attachment = $assembly->getMasterPictureAttachment(); - if ($this->isAttachmentValidPicture($attachment)) { - $list[] = $attachment; - } - - //Then comes the other images of the assembly - foreach ($assembly->getAttachments() as $attachment) { - //Dont show the master attachment twice - if ($this->isAttachmentValidPicture($attachment) && $attachment !== $assembly->getMasterPictureAttachment()) { - $list[] = $attachment; - } - } - - return $list; - } - - /** - * Determines what attachment should be used for previewing a assembly (especially in assembly table). - * The returned attachment is guaranteed to be existing and be a picture. - * - * @param Assembly $assembly The assembly for which the attachment should be determined - */ - public function getTablePreviewAttachment(Assembly $assembly): ?Attachment - { - $attachment = $assembly->getMasterPictureAttachment(); - if ($this->isAttachmentValidPicture($attachment)) { - return $attachment; - } - - return null; - } - - /** - * Checks if a attachment is exising and a valid picture. - * - * @param Attachment|null $attachment the attachment that should be checked - * - * @return bool true if the attachment is valid - */ - protected function isAttachmentValidPicture(?Attachment $attachment): bool - { - return $attachment instanceof Attachment - && $attachment->isPicture() - && $this->attachmentHelper->isFileExisting($attachment); - } -} diff --git a/src/Services/ProjectSystem/ProjectBuildHelper.php b/src/Services/ProjectSystem/ProjectBuildHelper.php index d7ba9e6c..269c7e4c 100644 --- a/src/Services/ProjectSystem/ProjectBuildHelper.php +++ b/src/Services/ProjectSystem/ProjectBuildHelper.php @@ -22,13 +22,10 @@ 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; /** @@ -36,10 +33,8 @@ use App\Services\Parts\PartLotWithdrawAddHelper; */ class ProjectBuildHelper { - public function __construct( - private readonly PartLotWithdrawAddHelper $withdrawAddHelper, - private readonly AssemblyBuildHelper $assemblyBuildHelper - ) { + public function __construct(private readonly PartLotWithdrawAddHelper $withdraw_add_helper) + { } /** @@ -71,16 +66,12 @@ 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() && $bom_entry->getAssembly() === null) { + if (!$bom_entry->isPartBomEntry()) { continue; } //The maximum buildable count for the whole project 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->getAssembly() !== null) { - $maximum_buildable_count = min($maximum_buildable_count, $this->assemblyBuildHelper->getMaximumBuildableCount($bom_entry->getAssembly())); - } + $maximum_buildable_count = min($maximum_buildable_count, $this->getMaximumBuildableCountForBOMEntry($bom_entry)); } return $maximum_buildable_count; @@ -106,10 +97,10 @@ class ProjectBuildHelper } /** - * Returns the project or assembly BOM entries for which parts are missing in the stock for the given number of builds + * Returns the project 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[]|AssemblyBOMEntry[] + * @return ProjectBOMEntry[] */ public function getNonBuildableProjectBomEntries(Project $project, int $number_of_builds = 1): array { @@ -117,29 +108,24 @@ class ProjectBuildHelper throw new \InvalidArgumentException('The number of builds must be greater than 0!'); } - $nonBuildableEntries = []; + $non_buildable_entries = []; foreach ($project->getBomEntries() as $bomEntry) { $part = $bomEntry->getPart(); //Skip BOM entries without a part (as we can not determine that) - if (!$part instanceof Part && $bomEntry->getAssembly() === null) { + if (!$part instanceof Part) { continue; } - if ($bomEntry->getPart() !== null) { - $amount_sum = $part->getAmountSum(); + $amount_sum = $part->getAmountSum(); - 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); + if ($amount_sum < $bomEntry->getQuantity() * $number_of_builds) { + $non_buildable_entries[] = $bomEntry; } } - return $nonBuildableEntries; + return $non_buildable_entries; } /** @@ -147,37 +133,22 @@ class ProjectBuildHelper * The ProjectBuildRequest has to be validated before!! * You have to flush changes to DB afterward */ - public function doBuild(ProjectBuildRequest $projectBuildRequest): void + public function doBuild(ProjectBuildRequest $buildRequest): void { - $message = $projectBuildRequest->getComment(); - $message .= ' (Project build: '.$projectBuildRequest->getProject()->getName().')'; + $message = $buildRequest->getComment(); + $message .= ' (Project build: '.$buildRequest->getProject()->getName().')'; - foreach ($projectBuildRequest->getPartBomEntries() as $bomEntry) { - foreach ($projectBuildRequest->getPartLotsForBOMEntry($bomEntry) as $partLot) { - $amount = $projectBuildRequest->getLotWithdrawAmount($partLot); + foreach ($buildRequest->getPartBomEntries() as $bom_entry) { + foreach ($buildRequest->getPartLotsForBOMEntry($bom_entry) as $part_lot) { + $amount = $buildRequest->getLotWithdrawAmount($part_lot); if ($amount > 0) { - $this->withdrawAddHelper->withdraw($partLot, $amount, $message); + $this->withdraw_add_helper->withdraw($part_lot, $amount, $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); + if ($buildRequest->getAddBuildsToBuildsPart()) { + $this->withdraw_add_helper->add($buildRequest->getBuildsPartLot(), $buildRequest->getNumberOfBuilds(), $message); } } } diff --git a/templates/form/collection_types_layout.html.twig b/templates/form/collection_types_layout.html.twig index 552fd542..96b71bf0 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.partOrAssembly{% endtrans %} + {% trans %}project.bom.part{% endtrans %} {% trans %}project.bom.name{% endtrans %} {# Remove button #} @@ -41,21 +41,9 @@ {{ form_widget(form.quantity) }} {{ form_errors(form.quantity) }} - - {{ form_row(form.part) }} + + {{ form_widget(form.part) }} {{ form_errors(form.part) }} - - {% if form.vars.value is not null and form.vars.value.project is not null %} - {% set hasAssembly = false %} - {% if is_granted("@assemblies.read") or has_assembly(form.vars.value.project.bomEntries.toArray) %} -
- {{ form_widget(form.assembly) }} - {{ form_errors(form.assembly) }} - {% endif %} - {% elseif is_granted("@assemblies.read") %} - {{ form_widget(form.assembly) }} - {{ form_errors(form.assembly) }} - {% endif %} {{ form_widget(form.name) }} diff --git a/templates/projects/build/_form.html.twig b/templates/projects/build/_form.html.twig index 7775fd2a..b25ca81e 100644 --- a/templates/projects/build/_form.html.twig +++ b/templates/projects/build/_form.html.twig @@ -27,9 +27,7 @@ {% if bom_entry.part %} - {{ '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 %} + {{ bom_entry.part.name }} {% if bom_entry.name %}({{ bom_entry.name }}){% endif %} {% else %} {{ bom_entry.name }} {% endif %} @@ -47,29 +45,9 @@ {% 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 4e557b6a..3c044e36 100644 --- a/translations/messages.cs.xlf +++ b/translations/messages.cs.xlf @@ -9906,18 +9906,6 @@ Element 3 Díl - - - project.bom.assembly - Baugruppe - - - - - project.bom.partOrAssembly - Auswahl - - project.bom.add_entry diff --git a/translations/messages.da.xlf b/translations/messages.da.xlf index 2e3b9814..cee4f08c 100644 --- a/translations/messages.da.xlf +++ b/translations/messages.da.xlf @@ -4820,18 +4820,6 @@ 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 @@ -9932,18 +9920,6 @@ Element 3 Komponent - - - project.bom.assembly - Baugruppe - - - - - project.bom.partOrAssembly - Auswahl - - project.bom.add_entry @@ -10340,12 +10316,6 @@ Element 3 På lager - - - project.builds.no_stock - intet lager angivet - - project.builds.needed @@ -10418,12 +10388,6 @@ 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 628cac91..5e48f9e7 100644 --- a/translations/messages.de.xlf +++ b/translations/messages.de.xlf @@ -9986,18 +9986,6 @@ Element 1 -> Element 1.2 Bauteil - - - project.bom.assembly - Baugruppe - - - - - project.bom.partOrAssembly - Auswahl - - project.bom.add_entry @@ -10430,12 +10418,6 @@ Element 1 -> Element 1.2 vorhanden - - - project.builds.no_stock - kein Lager angegeben - - project.builds.needed @@ -10508,12 +10490,6 @@ Element 1 -> Element 1.2 Ziel-Bestand - - - project.build.builds_part_lot_label - %name% (%quantity% benötigt) - - project.builds.number_of_builds @@ -13740,6 +13716,12 @@ Bitte beachten Sie, dass Sie sich nicht als deaktivierter Benutzer ausgeben kön benötigt + + + assembly.bom.delete.confirm + Wollen sie diesen Eintrag wirklich löschen? + + assembly.add_parts_to_assembly diff --git a/translations/messages.el.xlf b/translations/messages.el.xlf index ad8e5f68..176d2a2f 100644 --- a/translations/messages.el.xlf +++ b/translations/messages.el.xlf @@ -2620,22 +2620,10 @@ %value% (Μέρος) - + - part.table.name.value.for_assembly - %value% (Συναρμολόγηση) - - - - - project.bom.assembly - Συναρμολόγηση - - - - - project.bom.partOrAssembly - Επιλογή + part.table.name.value.for_project + %value% (Έργο) @@ -2674,18 +2662,6 @@ Αρχειοθετήθηκε - - - project.builds.no_stock - δεν έχει καθοριστεί απόθεμα - - - - - project.build.builds_part_lot_label - %name% (%quantity% απαιτείται) - - assembly.label @@ -2914,12 +2890,24 @@ απαιτούμενο + + + assembly.bom.delete.confirm + Θέλετε πραγματικά να διαγράψετε αυτήν την εγγραφή; + + assembly.add_parts_to_assembly Προσθήκη εξαρτημάτων στη συναρμολόγηση + + + assembly.bom.project + έργο + + assembly.bom.name @@ -2956,9 +2944,9 @@ Εισαγωγή εξαρτημάτων συναρμολόγησης - + - assembly.bom.part + assembly.bom.partOrProject Εξάρτημα @@ -3405,41 +3393,5 @@ - - - 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 22e4a4cc..694f7676 100644 --- a/translations/messages.en.xlf +++ b/translations/messages.en.xlf @@ -9999,18 +9999,6 @@ Element 1 -> Element 1.2 Part - - - project.bom.assembly - Assembly - - - - - project.bom.partOrAssembly - Selection - - project.bom.add_entry @@ -10407,12 +10395,6 @@ Element 1 -> Element 1.2 stocked - - - project.builds.no_stock - no stock specified - - project.builds.needed @@ -10485,12 +10467,6 @@ 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 66e93680..999fd71a 100644 --- a/translations/messages.es.xlf +++ b/translations/messages.es.xlf @@ -9930,18 +9930,6 @@ Elemento 3 Componente - - - project.bom.assembly - Baugruppe - - - - - project.bom.partOrAssembly - Auswahl - - project.bom.add_entry @@ -10338,12 +10326,6 @@ Elemento 3 Almacenado - - - project.builds.no_stock - no se ha especificado stock - - project.builds.needed @@ -10416,12 +10398,6 @@ 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 68125368..951a1bd3 100644 --- a/translations/messages.it.xlf +++ b/translations/messages.it.xlf @@ -9932,18 +9932,6 @@ Element 3 Componente - - - project.bom.assembly - Assemblaggio - - - - - project.bom.partOrAssembly - Selezione - - project.bom.add_entry @@ -10340,12 +10328,6 @@ Element 3 a magazzino - - - project.builds.no_stock - nessuna scorta specificata - - project.builds.needed @@ -10418,12 +10400,6 @@ 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 fb772306..101afd62 100644 --- a/translations/messages.ja.xlf +++ b/translations/messages.ja.xlf @@ -8960,18 +8960,6 @@ Exampletown Part-DBについての質問は、<a href="%href%" class="link-external" target="_blank">GitHub</a> にスレッドがあります。 - - - project.bom.assembly - アセンブリ - - - - - project.bom.partOrAssembly - 選択 - - assembly.edit.status @@ -9008,18 +8996,6 @@ 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 5654d1de..d9d4eac2 100644 --- a/translations/messages.pl.xlf +++ b/translations/messages.pl.xlf @@ -10331,12 +10331,6 @@ Element 3 dostępny - - - project.builds.no_stock - brak podanego stanu magazynowego - - project.builds.needed @@ -10409,12 +10403,6 @@ 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 326044b8..5850914f 100644 --- a/translations/messages.ru.xlf +++ b/translations/messages.ru.xlf @@ -9939,18 +9939,6 @@ Компонент - - - project.bom.assembly - Сборка - - - - - project.bom.partOrAssembly - Выбор - - project.bom.add_entry @@ -10347,12 +10335,6 @@ запасено - - - project.builds.no_stock - склад не указан - - project.builds.needed @@ -10425,12 +10407,6 @@ Целевой лот - - - project.build.builds_part_lot_label - %name% (требуется: %quantity%) - - project.builds.number_of_builds @@ -13122,6 +13098,12 @@ Добавить детали в сборку + + + assembly.bom.project + Проект + + part.info.add_part_to_assembly diff --git a/translations/messages.zh.xlf b/translations/messages.zh.xlf index aa730c08..a3e44de6 100644 --- a/translations/messages.zh.xlf +++ b/translations/messages.zh.xlf @@ -9938,18 +9938,6 @@ Element 3 部件 - - - project.bom.assembly - 装配 - - - - - project.bom.partOrAssembly - 选择 - - project.bom.add_entry @@ -10346,12 +10334,6 @@ Element 3 在库 - - - project.builds.no_stock - 未指定库存 - - project.builds.needed @@ -10424,12 +10406,6 @@ Element 3 目标批次 - - - project.build.builds_part_lot_label - %name% (需求数量: %quantity%) - - project.builds.number_of_builds diff --git a/translations/validators.en.xlf b/translations/validators.en.xlf index 89677cb4..08d3f2df 100644 --- a/translations/validators.en.xlf +++ b/translations/validators.en.xlf @@ -429,6 +429,7 @@ validator.assembly.bom_entry.name_or_part_needed You must select a part or set a name for the entry! + You must select a part or set a name for the entry!