Allow to filter by the number of part lots.

This commit is contained in:
Jan Böhmer 2022-08-28 19:39:16 +02:00
parent 99b25fb293
commit b8c77ca855
4 changed files with 63 additions and 3 deletions

View file

@ -7,6 +7,23 @@ use Doctrine\ORM\QueryBuilder;
trait FilterTrait
{
protected $useHaving = false;
public function useHaving($value = true): self
{
$this->useHaving = $value;
return $this;
}
/**
* Checks if the given input is an aggregateFunction like COUNT(part.partsLot) or so
* @return bool
*/
protected function isAggregateFunctionString(string $input): bool
{
return preg_match('/^[a-zA-Z]+\(.*\)$/', $input) === 1;
}
/**
* Generates a parameter identifier that can be used for the given property. It gives random results, to be unique, so you have to cache it.
* @param string $property
@ -14,7 +31,10 @@ trait FilterTrait
*/
protected function generateParameterIdentifier(string $property): string
{
return str_replace('.', '_', $property) . '_' . uniqid("", false);
//Replace all special characters with underscores
$property = preg_replace('/[^a-zA-Z0-9_]/', '_', $property);
//Add a random number to the end of the property name for uniqueness
return $property . '_' . uniqid("", false);
}
/**
@ -27,7 +47,12 @@ trait FilterTrait
*/
protected function addSimpleAndConstraint(QueryBuilder $queryBuilder, string $property, string $parameterIdentifier, string $comparison_operator, $value): void
{
$queryBuilder->andWhere(sprintf("%s %s (:%s)", $property, $comparison_operator, $parameterIdentifier));
if($this->useHaving || $this->isAggregateFunctionString($property)) { //If the property is an aggregate function, we have to use the "having" instead of the "where"
$queryBuilder->andHaving(sprintf("%s %s (:%s)", $property, $comparison_operator, $parameterIdentifier));
} else {
$queryBuilder->andWhere(sprintf("%s %s (:%s)", $property, $comparison_operator, $parameterIdentifier));
}
$queryBuilder->setParameter($parameterIdentifier, $value);
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace App\DataTables\Filters\Constraints;
use Doctrine\ORM\QueryBuilder;
class IntConstraint extends NumberConstraint
{
public function apply(QueryBuilder $queryBuilder): void
{
if($this->value1 !== null) {
$this->value1 = (int) $this->value1;
}
if($this->value2 !== null) {
$this->value2 = (int) $this->value2;
}
parent::apply($queryBuilder);
}
}

View file

@ -5,6 +5,7 @@ namespace App\DataTables\Filters;
use App\DataTables\Filters\Constraints\BooleanConstraint;
use App\DataTables\Filters\Constraints\DateTimeConstraint;
use App\DataTables\Filters\Constraints\EntityConstraint;
use App\DataTables\Filters\Constraints\IntConstraint;
use App\DataTables\Filters\Constraints\NumberConstraint;
use App\DataTables\Filters\Constraints\Part\TagsConstraint;
use App\DataTables\Filters\Constraints\TextConstraint;
@ -70,6 +71,9 @@ class PartFilter implements FilterInterface
/** @var EntityConstraint */
protected $storelocation;
/** @var NumberConstraint */
protected $lotCount;
/** @var EntityConstraint */
protected $measurementUnit;
@ -92,7 +96,7 @@ class PartFilter implements FilterInterface
$this->needsReview = new BooleanConstraint('part.needs_review');
$this->measurementUnit = new EntityConstraint($nodesListBuilder, MeasurementUnit::class, 'part.partUnit');
$this->mass = new NumberConstraint('part.mass');
$this->dbId = new NumberConstraint('part.id');
$this->dbId = new IntConstraint('part.id');
$this->addedDate = new DateTimeConstraint('part.addedDate');
$this->lastModified = new DateTimeConstraint('part.lastModified');
@ -104,6 +108,7 @@ class PartFilter implements FilterInterface
$this->manufacturer_product_url = new TextConstraint('part.manufacturer_product_url');
$this->storelocation = new EntityConstraint($nodesListBuilder, Storelocation::class, 'partLots.storage_location');
$this->lotCount = new IntConstraint('COUNT(partLots)');
}
public function apply(QueryBuilder $queryBuilder): void
@ -244,6 +249,11 @@ class PartFilter implements FilterInterface
return $this->manufacturer_product_number;
}
public function getLotCount(): NumberConstraint
{
return $this->lotCount;
}
/**
* @return TagsConstraint
*/

View file

@ -142,6 +142,11 @@ class PartFilterType extends AbstractType
'min' => 0,
]);
$builder->add('lotCount', NumberConstraintType::class, [
'label' => 'part.filter.lot_count',
'min' => 0
]);
$builder->add('submit', SubmitType::class, [
'label' => 'Update',