Projekt BOM-Konfiguration um Assemblies bereinigen.

Assembly BOM-Konfiguration um Projektauswahl erweitern (APS-3, APS-4)
This commit is contained in:
Marcel Diegelmann 2025-06-17 11:28:42 +02:00
parent f79dc3a102
commit df2ce45e4c
53 changed files with 738 additions and 1541 deletions

View file

@ -27,14 +27,17 @@ use App\Entity\AssemblySystem\AssemblyBOMEntry;
use App\Entity\Parts\Part;
use App\Helpers\Assemblies\AssemblyBuildRequest;
use App\Services\Parts\PartLotWithdrawAddHelper;
use App\Services\ProjectSystem\ProjectBuildHelper;
/**
* @see \App\Tests\Services\AssemblySystem\AssemblyBuildHelperTest
*/
class AssemblyBuildHelper
{
public function __construct(private readonly PartLotWithdrawAddHelper $withdraw_add_helper)
{
public function __construct(
private readonly PartLotWithdrawAddHelper $withdraw_add_helper,
private readonly ProjectBuildHelper $projectBuildHelper
) {
}
/**
@ -66,12 +69,16 @@ class AssemblyBuildHelper
$maximum_buildable_count = PHP_INT_MAX;
foreach ($assembly->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->getProject() === null) {
continue;
}
//The maximum buildable count for the whole assembly is the minimum of all BOM entries
$maximum_buildable_count = min($maximum_buildable_count, $this->getMaximumBuildableCountForBOMEntry($bom_entry));
//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->getProject() !== null) {
$maximum_buildable_count = min($maximum_buildable_count, $this->projectBuildHelper->getMaximumBuildableCount($bom_entry->getProject()));
}
}
return $maximum_buildable_count;
@ -97,7 +104,7 @@ class AssemblyBuildHelper
}
/**
* Returns the 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 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[]
@ -108,24 +115,29 @@ class AssemblyBuildHelper
throw new \InvalidArgumentException('The number of builds must be greater than 0!');
}
$non_buildable_entries = [];
$nonBuildableEntries = [];
foreach ($assembly->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->projectBuildHelper->getNonBuildableProjectBomEntries($bomEntry->getProject(), $number_of_builds);
$nonBuildableEntries = array_merge($nonBuildableEntries, $nonBuildableAssemblyEntries);
}
}
return $non_buildable_entries;
return $nonBuildableEntries;
}
/**

View file

@ -22,38 +22,38 @@ declare(strict_types=1);
namespace App\Services\Attachments;
use App\Entity\AssemblySystem\Assembly;
use App\Entity\Attachments\Attachment;
use App\Entity\ProjectSystem\Project;
class AssemblyPreviewGenerator
class ProjectPreviewGenerator
{
public function __construct(protected AttachmentManager $attachmentHelper)
{
}
/**
* Returns a list of attachments that can be used for previewing the assembly ordered by priority.
* Returns a list of attachments that can be used for previewing the project ordered by priority.
*
* @param Assembly $assembly the assembly for which the attachments should be determined
* @param Project $project the project for which the attachments should be determined
*
* @return (Attachment|null)[]
*
* @psalm-return list<Attachment|null>
*/
public function getPreviewAttachments(Assembly $assembly): array
public function getPreviewAttachments(Project $project): array
{
$list = [];
//Master attachment has top priority
$attachment = $assembly->getMasterPictureAttachment();
$attachment = $project->getMasterPictureAttachment();
if ($this->isAttachmentValidPicture($attachment)) {
$list[] = $attachment;
}
//Then comes the other images of the assembly
foreach ($assembly->getAttachments() as $attachment) {
//Then comes the other images of the project
foreach ($project->getAttachments() as $attachment) {
//Dont show the master attachment twice
if ($this->isAttachmentValidPicture($attachment) && $attachment !== $assembly->getMasterPictureAttachment()) {
if ($this->isAttachmentValidPicture($attachment) && $attachment !== $project->getMasterPictureAttachment()) {
$list[] = $attachment;
}
}
@ -62,14 +62,14 @@ class AssemblyPreviewGenerator
}
/**
* Determines what attachment should be used for previewing a assembly (especially in assembly table).
* Determines what attachment should be used for previewing a project (especially in project 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
* @param Project $project The project for which the attachment should be determined
*/
public function getTablePreviewAttachment(Assembly $assembly): ?Attachment
public function getTablePreviewAttachment(Project $project): ?Attachment
{
$attachment = $assembly->getMasterPictureAttachment();
$attachment = $project->getMasterPictureAttachment();
if ($this->isAttachmentValidPicture($attachment)) {
return $attachment;
}

View file

@ -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);
}
}
}