Assembly-Filter und -Tab ergänzen

Fügt Unterstützung für Assembly-Filter in der Suche sowie ein neues Tab für Assemblies in der Filteransicht hinzu. Anpassungen beinhalten Änderungen an Datenbankabfragen, Formularen und Templates.
This commit is contained in:
Marcel Diegelmann 2025-12-12 10:47:05 +01:00
parent 980657eec4
commit 07d4ffa956
7 changed files with 75 additions and 3 deletions

View file

@ -330,7 +330,7 @@ class PartListsController extends AbstractController
$filter->setSupplier($request->query->getBoolean('supplier')); $filter->setSupplier($request->query->getBoolean('supplier'));
$filter->setManufacturer($request->query->getBoolean('manufacturer')); $filter->setManufacturer($request->query->getBoolean('manufacturer'));
$filter->setFootprint($request->query->getBoolean('footprint')); $filter->setFootprint($request->query->getBoolean('footprint'));
$filter->setAssembly($request->query->getBoolean('assembly'));
$filter->setRegex($request->query->getBoolean('regex')); $filter->setRegex($request->query->getBoolean('regex'));

View file

@ -36,6 +36,7 @@ use App\DataTables\Filters\Constraints\Part\LessThanDesiredConstraint;
use App\DataTables\Filters\Constraints\Part\ParameterConstraint; use App\DataTables\Filters\Constraints\Part\ParameterConstraint;
use App\DataTables\Filters\Constraints\Part\TagsConstraint; use App\DataTables\Filters\Constraints\Part\TagsConstraint;
use App\DataTables\Filters\Constraints\TextConstraint; use App\DataTables\Filters\Constraints\TextConstraint;
use App\Entity\AssemblySystem\Assembly;
use App\Entity\Attachments\AttachmentType; use App\Entity\Attachments\AttachmentType;
use App\Entity\Parts\Category; use App\Entity\Parts\Category;
use App\Entity\Parts\Footprint; use App\Entity\Parts\Footprint;
@ -107,6 +108,14 @@ class PartFilter implements FilterInterface
public readonly TextConstraint $bomName; public readonly TextConstraint $bomName;
public readonly TextConstraint $bomComment; public readonly TextConstraint $bomComment;
/*************************************************
* Assembly
*************************************************/
public readonly EntityConstraint $assembly;
public readonly NumberConstraint $assemblyBomQuantity;
public readonly TextConstraint $assemblyBomName;
/************************************************* /*************************************************
* Bulk Import Job tab * Bulk Import Job tab
*************************************************/ *************************************************/
@ -180,6 +189,10 @@ class PartFilter implements FilterInterface
$this->bomName = new TextConstraint('_projectBomEntries.name'); $this->bomName = new TextConstraint('_projectBomEntries.name');
$this->bomComment = new TextConstraint('_projectBomEntries.comment'); $this->bomComment = new TextConstraint('_projectBomEntries.comment');
$this->assembly = new EntityConstraint($nodesListBuilder, Assembly::class, '_assemblyBomEntries.assembly');
$this->assemblyBomQuantity = new NumberConstraint('_assemblyBomEntries.quantity');
$this->assemblyBomName = new TextConstraint('_assemblyBomEntries.name');
// Bulk Import Job filters // Bulk Import Job filters
$this->inBulkImportJob = new BulkImportJobExistsConstraint(); $this->inBulkImportJob = new BulkImportJobExistsConstraint();
$this->bulkImportJobStatus = new BulkImportJobStatusConstraint(); $this->bulkImportJobStatus = new BulkImportJobStatusConstraint();

View file

@ -66,6 +66,9 @@ class PartSearchFilter implements FilterInterface
/** @var bool Use Internal Part number for searching */ /** @var bool Use Internal Part number for searching */
protected bool $ipn = true; protected bool $ipn = true;
/** @var bool Use assembly name for searching */
protected bool $assembly = true;
public function __construct( public function __construct(
/** @var string The string to query for */ /** @var string The string to query for */
protected string $keyword protected string $keyword
@ -113,6 +116,9 @@ class PartSearchFilter implements FilterInterface
if ($this->ipn) { if ($this->ipn) {
$fields_to_search[] = 'part.ipn'; $fields_to_search[] = 'part.ipn';
} }
if ($this->assembly) {
$fields_to_search[] = '_assembly.name';
}
return $fields_to_search; return $fields_to_search;
} }
@ -304,5 +310,14 @@ class PartSearchFilter implements FilterInterface
return $this; return $this;
} }
public function isAssembly(): bool
{
return $this->assembly;
}
public function setAssembly(bool $assembly): PartSearchFilter
{
$this->assembly = $assembly;
return $this;
}
} }

View file

@ -474,6 +474,13 @@ final class PartsDataTable implements DataTableTypeInterface
//Do not group by many-to-* relations, as it would restrict the COUNT having clauses to be maximum 1 //Do not group by many-to-* relations, as it would restrict the COUNT having clauses to be maximum 1
//$builder->addGroupBy('_projectBomEntries'); //$builder->addGroupBy('_projectBomEntries');
} }
if (str_contains($dql, '_assembly.')) {
$builder->leftJoin('part.assembly_bom_entries', '_assemblyBomEntries');
$builder->leftJoin('_assemblyBomEntries.assembly', '_assembly');
}
if (str_contains($dql, '_assemblyBomEntries')) {
$builder->leftJoin('part.assembly_bom_entries', '_assemblyBomEntries');
}
if (str_contains($dql, '_jobPart')) { if (str_contains($dql, '_jobPart')) {
$builder->leftJoin('part.bulkImportJobParts', '_jobPart'); $builder->leftJoin('part.bulkImportJobParts', '_jobPart');
$builder->leftJoin('_jobPart.job', '_bulkImportJob'); $builder->leftJoin('_jobPart.job', '_bulkImportJob');

View file

@ -25,6 +25,7 @@ namespace App\Form\Filters;
use App\DataTables\Filters\Constraints\Part\BulkImportPartStatusConstraint; use App\DataTables\Filters\Constraints\Part\BulkImportPartStatusConstraint;
use App\DataTables\Filters\Constraints\Part\ParameterConstraint; use App\DataTables\Filters\Constraints\Part\ParameterConstraint;
use App\DataTables\Filters\PartFilter; use App\DataTables\Filters\PartFilter;
use App\Entity\AssemblySystem\Assembly;
use App\Entity\Attachments\AttachmentType; use App\Entity\Attachments\AttachmentType;
use App\Entity\InfoProviderSystem\BulkImportJobStatus; use App\Entity\InfoProviderSystem\BulkImportJobStatus;
use App\Entity\InfoProviderSystem\BulkImportPartStatus; use App\Entity\InfoProviderSystem\BulkImportPartStatus;
@ -313,6 +314,26 @@ class PartFilterType extends AbstractType
} }
/**************************************************************************
* Assembly tab
**************************************************************************/
if ($this->security->isGranted('read', Assembly::class)) {
$builder
->add('assembly', StructuralEntityConstraintType::class, [
'label' => 'assembly.label',
'entity_class' => Assembly::class
])
->add('assemblyBomQuantity', NumberConstraintType::class, [
'label' => 'assembly.bom.quantity',
'min' => 0,
'step' => "any",
])
->add('assemblyBomName', TextConstraintType::class, [
'label' => 'assembly.bom.name',
])
;
}
/************************************************************************** /**************************************************************************
* Bulk Import Job tab * Bulk Import Job tab
**************************************************************************/ **************************************************************************/

View file

@ -61,6 +61,10 @@
<label for="search_footprint" class="form-check-label justify-content-start">{% trans %}footprint.label{% endtrans %}</label> <label for="search_footprint" class="form-check-label justify-content-start">{% trans %}footprint.label{% endtrans %}</label>
</div> </div>
{% endif %} {% endif %}
<div class="form-check">
<input type="checkbox" class="form-check-input" id="search_assembly" name="assembly" value="1" {{ stimulus_controller('elements/localStorage_checkbox') }}>
<label for="search_assembly" class="form-check-label justify-content-start">{% trans %}assembly.label{% endtrans %}</label>
</div>
<hr> <hr>
<div class="form-check"> <div class="form-check">
<input type="checkbox" class="form-check-input" id="regex" name="regex" value="1" {{ stimulus_controller('elements/localStorage_checkbox') }}> <input type="checkbox" class="form-check-input" id="regex" name="regex" value="1" {{ stimulus_controller('elements/localStorage_checkbox') }}>
@ -102,4 +106,4 @@
{{ _self.settings_drodown(is_navbar) }} {{ _self.settings_drodown(is_navbar) }}
{% endif %} {% endif %}
</form> </form>
{% endmacro %} {% endmacro %}

View file

@ -31,6 +31,11 @@
<button class="nav-link" id="filter-projects-tab" data-bs-toggle="tab" data-bs-target="#filter-projects"><i class="fas fa-archive fa-fw"></i> {% trans %}project.labelp{% endtrans %}</button> <button class="nav-link" id="filter-projects-tab" data-bs-toggle="tab" data-bs-target="#filter-projects"><i class="fas fa-archive fa-fw"></i> {% trans %}project.labelp{% endtrans %}</button>
</li> </li>
{% endif %} {% endif %}
{% if filterForm.assembly is defined %}
<li class="nav-item" role="presentation">
<button class="nav-link" id="filter-assemblies-tab" data-bs-toggle="tab" data-bs-target="#filter-assemblies"><i class="fas fa-archive fa-fw"></i> {% trans %}assembly.labelp{% endtrans %}</button>
</li>
{% endif %}
{% if filterForm.inBulkImportJob is defined %} {% if filterForm.inBulkImportJob is defined %}
<li class="nav-item" role="presentation"> <li class="nav-item" role="presentation">
<button class="nav-link" id="filter-bulk-import-tab" data-bs-toggle="tab" data-bs-target="#filter-bulk-import"><i class="fas fa-download fa-fw"></i> {% trans %}part.edit.tab.bulk_import{% endtrans %}</button> <button class="nav-link" id="filter-bulk-import-tab" data-bs-toggle="tab" data-bs-target="#filter-bulk-import"><i class="fas fa-download fa-fw"></i> {% trans %}part.edit.tab.bulk_import{% endtrans %}</button>
@ -132,6 +137,13 @@
{{ form_row(filterForm.bomComment) }} {{ form_row(filterForm.bomComment) }}
</div> </div>
{% endif %} {% endif %}
{% if filterForm.assembly is defined %}
<div class="tab-pane pt-3" id="filter-assemblies" role="tabpanel" aria-labelledby="filter-assemblies-tab" tabindex="0">
{{ form_row(filterForm.assembly) }}
{{ form_row(filterForm.assemblyBomQuantity) }}
{{ form_row(filterForm.assemblyBomName) }}
</div>
{% endif %}
{% if filterForm.inBulkImportJob is defined %} {% if filterForm.inBulkImportJob is defined %}
<div class="tab-pane pt-3" id="filter-bulk-import" role="tabpanel" aria-labelledby="filter-bulk-import-tab" tabindex="0"> <div class="tab-pane pt-3" id="filter-bulk-import" role="tabpanel" aria-labelledby="filter-bulk-import-tab" tabindex="0">
{{ form_row(filterForm.inBulkImportJob) }} {{ form_row(filterForm.inBulkImportJob) }}
@ -163,4 +175,4 @@
{{ form_end(filterForm) }} {{ form_end(filterForm) }}
</div> </div>
</div> </div>
</div> </div>