mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2026-04-15 19:09:36 +00:00
Fix #1305: Enable BOM sorting on part fields (Storage location, Manufacturing status) and fix BOM table query/pagination issues (#1338)
Some checks failed
Build assets artifact / Build assets artifact (push) Has been cancelled
Docker Image Build / build (linux/amd64, amd64, ubuntu-latest) (push) Has been cancelled
Docker Image Build / build (linux/arm/v7, armv7, ubuntu-24.04-arm) (push) Has been cancelled
Docker Image Build / build (linux/arm64, arm64, ubuntu-24.04-arm) (push) Has been cancelled
Docker Image Build (FrankenPHP) / build (linux/amd64, amd64, ubuntu-latest) (push) Has been cancelled
Docker Image Build (FrankenPHP) / build (linux/arm/v7, armv7, ubuntu-24.04-arm) (push) Has been cancelled
Docker Image Build (FrankenPHP) / build (linux/arm64, arm64, ubuntu-24.04-arm) (push) Has been cancelled
Static analysis / Static analysis (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.2, mysql) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.3, mysql) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.4, mysql) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.5, mysql) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.2, postgres) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.3, postgres) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.4, postgres) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.5, postgres) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.2, sqlite) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.3, sqlite) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.4, sqlite) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.5, sqlite) (push) Has been cancelled
Docker Image Build / merge (push) Has been cancelled
Docker Image Build (FrankenPHP) / merge (push) Has been cancelled
Some checks failed
Build assets artifact / Build assets artifact (push) Has been cancelled
Docker Image Build / build (linux/amd64, amd64, ubuntu-latest) (push) Has been cancelled
Docker Image Build / build (linux/arm/v7, armv7, ubuntu-24.04-arm) (push) Has been cancelled
Docker Image Build / build (linux/arm64, arm64, ubuntu-24.04-arm) (push) Has been cancelled
Docker Image Build (FrankenPHP) / build (linux/amd64, amd64, ubuntu-latest) (push) Has been cancelled
Docker Image Build (FrankenPHP) / build (linux/arm/v7, armv7, ubuntu-24.04-arm) (push) Has been cancelled
Docker Image Build (FrankenPHP) / build (linux/arm64, arm64, ubuntu-24.04-arm) (push) Has been cancelled
Static analysis / Static analysis (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.2, mysql) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.3, mysql) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.4, mysql) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.5, mysql) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.2, postgres) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.3, postgres) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.4, postgres) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.5, postgres) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.2, sqlite) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.3, sqlite) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.4, sqlite) (push) Has been cancelled
PHPUnit Tests / PHPUnit and coverage Test (PHP 8.5, sqlite) (push) Has been cancelled
Docker Image Build / merge (push) Has been cancelled
Docker Image Build (FrankenPHP) / merge (push) Has been cancelled
* Fix identation
* Allow ordering of column Storage Locations in BOM fix-#1152
* Fix "[Semantical Error] line 0, col 274 near 'storageLocations.name))': Error: 'storageLocations' is not defined." when trying to sort by column Storage Locations
* Try to fix "Iterate with fetch join in class App\Entity\Parts\PartLot using association part not allowed." when opening BOM
* Revert "Try to fix "Iterate with fetch join in class App\Entity\Parts\PartLot using association part not allowed." when opening BOM"
This reverts commit 5c5c7cece1.
* Try to fix "Iterate with fetch join in class App\Entity\Parts\PartLot using association part not allowed." when opening BOM 2nd try
* Remove alias to fix: Unknown named parameter $alias
* Reformat code to allow easier diff between ProjectBomEntriesDataTable.php and PartsDataTable.php
* Try if 'data' es really needed as it is not used in PartDataTable.php
* Use TwoStepORMAdapter to enable sorting based on other columns like storage location, manufacturing status
* Add readonly hint to projectBom query
---------
Co-authored-by: root <root@part-db.fritz.box>
Co-authored-by: Jan Böhmer <mail@jan-boehmer.de>
This commit is contained in:
parent
d25ac2622e
commit
0140c9a7b9
1 changed files with 84 additions and 23 deletions
|
|
@ -1,8 +1,5 @@
|
|||
<?php
|
||||
|
||||
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)
|
||||
|
|
@ -20,23 +17,28 @@ declare(strict_types=1);
|
|||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\DataTables;
|
||||
|
||||
use App\DataTables\Adapters\TwoStepORMAdapter;
|
||||
use App\DataTables\Column\EntityColumn;
|
||||
use App\DataTables\Column\EnumColumn;
|
||||
use App\DataTables\Column\LocaleDateTimeColumn;
|
||||
use App\DataTables\Column\MarkdownColumn;
|
||||
use App\DataTables\Helpers\PartDataTableHelper;
|
||||
use App\Entity\Attachments\Attachment;
|
||||
use App\Doctrine\Helpers\FieldHelper;
|
||||
use App\Entity\Parts\Part;
|
||||
use App\Entity\Parts\ManufacturingStatus;
|
||||
use App\Entity\ProjectSystem\ProjectBOMEntry;
|
||||
use App\Services\ElementTypeNameGenerator;
|
||||
use App\Services\EntityURLGenerator;
|
||||
use App\Services\Formatters\AmountFormatter;
|
||||
use Doctrine\ORM\AbstractQuery;
|
||||
use Doctrine\ORM\Query;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Omines\DataTablesBundle\Adapter\Doctrine\ORM\SearchCriteriaProvider;
|
||||
use Omines\DataTablesBundle\Adapter\Doctrine\ORMAdapter;
|
||||
use Omines\DataTablesBundle\Column\TextColumn;
|
||||
use Omines\DataTablesBundle\DataTable;
|
||||
use Omines\DataTablesBundle\DataTableTypeInterface;
|
||||
|
|
@ -44,9 +46,12 @@ use Symfony\Contracts\Translation\TranslatorInterface;
|
|||
|
||||
class ProjectBomEntriesDataTable implements DataTableTypeInterface
|
||||
{
|
||||
public function __construct(protected TranslatorInterface $translator, protected PartDataTableHelper $partDataTableHelper,
|
||||
protected EntityURLGenerator $entityURLGenerator, protected AmountFormatter $amountFormatter)
|
||||
{
|
||||
public function __construct(
|
||||
protected EntityURLGenerator $entityURLGenerator,
|
||||
protected TranslatorInterface $translator,
|
||||
protected AmountFormatter $amountFormatter,
|
||||
protected PartDataTableHelper $partDataTableHelper
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -62,7 +67,7 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface
|
|||
return '';
|
||||
}
|
||||
return $this->partDataTableHelper->renderPicture($context->getPart());
|
||||
},
|
||||
}
|
||||
])
|
||||
|
||||
->add('id', TextColumn::class, [
|
||||
|
|
@ -133,23 +138,24 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface
|
|||
->add('category', EntityColumn::class, [
|
||||
'label' => $this->translator->trans('part.table.category'),
|
||||
'property' => 'part.category',
|
||||
'orderField' => 'NATSORT(category.name)',
|
||||
'orderField' => 'NATSORT(category.name)'
|
||||
])
|
||||
->add('footprint', EntityColumn::class, [
|
||||
'property' => 'part.footprint',
|
||||
'label' => $this->translator->trans('part.table.footprint'),
|
||||
'orderField' => 'NATSORT(footprint.name)',
|
||||
'orderField' => 'NATSORT(footprint.name)'
|
||||
])
|
||||
|
||||
->add('manufacturer', EntityColumn::class, [
|
||||
'property' => 'part.manufacturer',
|
||||
'label' => $this->translator->trans('part.table.manufacturer'),
|
||||
'orderField' => 'NATSORT(manufacturer.name)',
|
||||
'orderField' => 'NATSORT(manufacturer.name)'
|
||||
])
|
||||
|
||||
->add('manufacturing_status', EnumColumn::class, [
|
||||
'label' => $this->translator->trans('part.table.manufacturingStatus'),
|
||||
'data' => static fn(ProjectBOMEntry $context): ?ManufacturingStatus => $context->getPart()?->getManufacturingStatus(),
|
||||
'data' => static fn(ProjectBOMEntry $context): ?ManufacturingStatus => $context->getPart()?->getManufacturingStatus(),
|
||||
'orderField' => 'part.manufacturing_status',
|
||||
'class' => ManufacturingStatus::class,
|
||||
'render' => function (?ManufacturingStatus $status, ProjectBOMEntry $context): string {
|
||||
if ($status === null) {
|
||||
|
|
@ -183,8 +189,10 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface
|
|||
return '';
|
||||
}
|
||||
])
|
||||
->add('storageLocations', TextColumn::class, [
|
||||
'label' => 'part.table.storeLocations',
|
||||
->add('storelocation', TextColumn::class, [
|
||||
'label' => $this->translator->trans('part.table.storeLocations'),
|
||||
//We need to use a aggregate function to get the first store location, as we have a one-to-many relation
|
||||
'orderField' => 'NATSORT(MIN(_storelocations.name))',
|
||||
'visible' => false,
|
||||
'render' => function ($value, ProjectBOMEntry $context) {
|
||||
if ($context->getPart() !== null) {
|
||||
|
|
@ -207,11 +215,13 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface
|
|||
|
||||
$dataTable->addOrderBy('name', DataTable::SORT_ASCENDING);
|
||||
|
||||
$dataTable->createAdapter(ORMAdapter::class, [
|
||||
'entity' => Attachment::class,
|
||||
'query' => function (QueryBuilder $builder) use ($options): void {
|
||||
$this->getQuery($builder, $options);
|
||||
$dataTable->createAdapter(TwoStepORMAdapter::class, [
|
||||
'entity' => ProjectBOMEntry::class,
|
||||
'hydrate' => AbstractQuery::HYDRATE_OBJECT,
|
||||
'filter_query' => function (QueryBuilder $builder) use ($options): void {
|
||||
$this->getFilterQuery($builder, $options);
|
||||
},
|
||||
'detail_query' => $this->getDetailQuery(...),
|
||||
'criteria' => [
|
||||
function (QueryBuilder $builder) use ($options): void {
|
||||
$this->buildCriteria($builder, $options);
|
||||
|
|
@ -221,20 +231,71 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface
|
|||
]);
|
||||
}
|
||||
|
||||
private function getQuery(QueryBuilder $builder, array $options): void
|
||||
private function getFilterQuery(QueryBuilder $builder, array $options): void
|
||||
{
|
||||
$builder->select('bom_entry')
|
||||
->addSelect('part')
|
||||
$builder
|
||||
->select('bom_entry.id')
|
||||
->from(ProjectBOMEntry::class, 'bom_entry')
|
||||
->leftJoin('bom_entry.part', 'part')
|
||||
->leftJoin('part.category', 'category')
|
||||
->leftJoin('part.partLots', '_partLots')
|
||||
->leftJoin('_partLots.storage_location', '_storelocations')
|
||||
->leftJoin('part.footprint', 'footprint')
|
||||
->leftJoin('part.manufacturer', 'manufacturer')
|
||||
->leftJoin('part.partCustomState', 'partCustomState')
|
||||
->where('bom_entry.project = :project')
|
||||
->setParameter('project', $options['project'])
|
||||
->addGroupBy('bom_entry')
|
||||
->addGroupBy('part')
|
||||
->addGroupBy('category')
|
||||
->addGroupBy('footprint')
|
||||
->addGroupBy('manufacturer')
|
||||
->addGroupBy('partCustomState')
|
||||
;
|
||||
}
|
||||
|
||||
private function getDetailQuery(QueryBuilder $builder, array $filter_results): void
|
||||
{
|
||||
$ids = array_map(static fn (array $row) => $row['id'], $filter_results);
|
||||
if ($ids === []) {
|
||||
$ids = [-1];
|
||||
}
|
||||
|
||||
$builder
|
||||
->select('bom_entry')
|
||||
->addSelect('part')
|
||||
->addSelect('category')
|
||||
->addSelect('partLots')
|
||||
->addSelect('storelocations')
|
||||
->addSelect('footprint')
|
||||
->addSelect('manufacturer')
|
||||
->addSelect('partCustomState')
|
||||
->from(ProjectBOMEntry::class, 'bom_entry')
|
||||
->leftJoin('bom_entry.part', 'part')
|
||||
->leftJoin('part.category', 'category')
|
||||
->leftJoin('part.partLots', 'partLots')
|
||||
->leftJoin('partLots.storage_location', 'storelocations')
|
||||
->leftJoin('part.footprint', 'footprint')
|
||||
->leftJoin('part.manufacturer', 'manufacturer')
|
||||
->leftJoin('part.partCustomState', 'partCustomState')
|
||||
->where('bom_entry.id IN (:ids)')
|
||||
->setParameter('ids', $ids)
|
||||
->addGroupBy('bom_entry')
|
||||
->addGroupBy('part')
|
||||
->addGroupBy('partLots')
|
||||
->addGroupBy('category')
|
||||
->addGroupBy('storelocations')
|
||||
->addGroupBy('footprint')
|
||||
->addGroupBy('manufacturer')
|
||||
->addGroupBy('partCustomState')
|
||||
|
||||
->setHint(Query::HINT_READ_ONLY, true)
|
||||
->setHint(Query::HINT_FORCE_PARTIAL_LOAD, false)
|
||||
;
|
||||
|
||||
FieldHelper::addOrderByFieldParam($builder, 'bom_entry.id', 'ids');
|
||||
}
|
||||
|
||||
private function buildCriteria(QueryBuilder $builder, array $options): void
|
||||
{
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue