From d3dcefb645f27f79e2e0ab660eb0e8c8618234f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hmer?= Date: Sun, 16 Jun 2024 23:26:57 +0200 Subject: [PATCH] Fixed total amount and less than desired filter on postgresql --- .../Constraints/Part/LessThanDesiredConstraint.php | 13 ++++++++++--- src/DataTables/Filters/PartFilter.php | 10 ++++++++-- tests/DatatablesAvailabilityTest.php | 4 ++++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/DataTables/Filters/Constraints/Part/LessThanDesiredConstraint.php b/src/DataTables/Filters/Constraints/Part/LessThanDesiredConstraint.php index eed37b8b..87292106 100644 --- a/src/DataTables/Filters/Constraints/Part/LessThanDesiredConstraint.php +++ b/src/DataTables/Filters/Constraints/Part/LessThanDesiredConstraint.php @@ -23,13 +23,20 @@ declare(strict_types=1); namespace App\DataTables\Filters\Constraints\Part; use App\DataTables\Filters\Constraints\BooleanConstraint; +use App\Entity\Parts\PartLot; use Doctrine\ORM\QueryBuilder; class LessThanDesiredConstraint extends BooleanConstraint { public function __construct(string $property = null, string $identifier = null, ?bool $default_value = null) { - parent::__construct($property ?? 'amountSum', $identifier, $default_value); + parent::__construct($property ?? '( + SELECT COALESCE(SUM(ld_partLot.amount), 0.0) + FROM '.PartLot::class.' ld_partLot + WHERE ld_partLot.part = part.id + AND ld_partLot.instock_unknown = false + AND (ld_partLot.expiration_date IS NULL OR ld_partLot.expiration_date > CURRENT_DATE()) + )', $identifier ?? 'amountSumLessThanDesired', $default_value); } public function apply(QueryBuilder $queryBuilder): void @@ -41,9 +48,9 @@ class LessThanDesiredConstraint extends BooleanConstraint //If value is true, we want to filter for parts with stock < desired stock if ($this->value) { - $queryBuilder->andHaving('amountSum < minamount'); + $queryBuilder->andHaving( $this->property . ' < minamount'); } else { - $queryBuilder->andHaving('amountSum >= minamount'); + $queryBuilder->andHaving($this->property . ' >= minamount'); } } } diff --git a/src/DataTables/Filters/PartFilter.php b/src/DataTables/Filters/PartFilter.php index 177b6dbd..ff98c76f 100644 --- a/src/DataTables/Filters/PartFilter.php +++ b/src/DataTables/Filters/PartFilter.php @@ -37,6 +37,7 @@ use App\Entity\Parts\Category; use App\Entity\Parts\Footprint; use App\Entity\Parts\Manufacturer; use App\Entity\Parts\MeasurementUnit; +use App\Entity\Parts\PartLot; use App\Entity\Parts\StorageLocation; use App\Entity\Parts\Supplier; use App\Entity\ProjectSystem\Project; @@ -123,8 +124,13 @@ class PartFilter implements FilterInterface This seems to be related to the fact, that PDO does not have an float parameter type and using string type does not work in this situation (at least in SQLite) TODO: Find a better solution here */ - //We have to use Having here, as we use an alias column which is not supported on the where clause and would result in an error - $this->amountSum = (new IntConstraint('amountSum'))->useHaving(); + $this->amountSum = (new IntConstraint('( + SELECT COALESCE(SUM(__partLot.amount), 0.0) + FROM '.PartLot::class.' __partLot + WHERE __partLot.part = part.id + AND __partLot.instock_unknown = false + AND (__partLot.expiration_date IS NULL OR __partLot.expiration_date > CURRENT_DATE()) + )', identifier: "amountSumWhere")); $this->lotCount = new IntConstraint('COUNT(_partLots)'); $this->lessThanDesired = new LessThanDesiredConstraint(); diff --git a/tests/DatatablesAvailabilityTest.php b/tests/DatatablesAvailabilityTest.php index 23bc6f92..5af04627 100644 --- a/tests/DatatablesAvailabilityTest.php +++ b/tests/DatatablesAvailabilityTest.php @@ -99,6 +99,10 @@ class DatatablesAvailabilityTest extends WebTestCase //Test using filters yield ['/category/1/parts?part_filter%5Bname%5D%5Boperator%5D=%3D&part_filter%5Bname%5D%5Bvalue%5D=BC547&part_filter%5Bcategory%5D%5Boperator%5D=INCLUDING_CHILDREN&part_filter%5Btags%5D%5Boperator%5D=ANY&part_filter%5Btags%5D%5Bvalue%5D=Test&part_filter%5Bsubmit%5D=']; yield ['/category/1/parts?part_filter%5Bcategory%5D%5Boperator%5D=INCLUDING_CHILDREN&part_filter%5Bstorelocation%5D%5Boperator%5D=%3D&part_filter%5Bstorelocation%5D%5Bvalue%5D=1&part_filter%5BattachmentsCount%5D%5Boperator%5D=%3D&part_filter%5BattachmentsCount%5D%5Bvalue1%5D=3&part_filter%5Bsubmit%5D=']; + //Filter over total amount + yield ['/parts?part_filter%5BamountSum%5D%5Boperator%5D=>&part_filter%5BamountSum%5D%5Bvalue1%5D=1&part_filter%5Bsubmit%5D=']; + //Less than desired filter: + yield ['/parts?part_filter%5BlessThanDesired%5D%5Bvalue%5D=true&part_filter%5Bsubmit%5D=']; //Test regex search yield ['/parts/search?category=1&comment=1&description=1&ipn=1&keyword=test&mpn=1&name=1&ordernr=1®ex=1&storelocation=1&tags=1'];