Allow to order and filter by the amount sum of parts.

This commit is contained in:
Jan Böhmer 2022-09-04 03:37:54 +02:00
parent ec5e956e31
commit 8f94a58c71
8 changed files with 42 additions and 3 deletions

View file

@ -33,3 +33,4 @@ doctrine:
dql: dql:
string_functions: string_functions:
regexp: DoctrineExtensions\Query\Mysql\Regexp regexp: DoctrineExtensions\Query\Mysql\Regexp
ifnull: DoctrineExtensions\Query\Mysql\IfNull

View file

@ -2,6 +2,7 @@
namespace App\DataTables\Filters\Constraints; namespace App\DataTables\Filters\Constraints;
use Doctrine\DBAL\ParameterType;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
trait FilterTrait trait FilterTrait

View file

@ -2,6 +2,7 @@
namespace App\DataTables\Filters\Constraints; namespace App\DataTables\Filters\Constraints;
use Doctrine\DBAL\ParameterType;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use \RuntimeException; use \RuntimeException;

View file

@ -19,7 +19,6 @@ use App\Entity\Parts\Storelocation;
use App\Entity\Parts\Supplier; use App\Entity\Parts\Supplier;
use App\Services\Trees\NodesListBuilder; use App\Services\Trees\NodesListBuilder;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Svg\Tag\Text;
class PartFilter implements FilterInterface class PartFilter implements FilterInterface
{ {
@ -83,6 +82,9 @@ class PartFilter implements FilterInterface
/** @var IntConstraint */ /** @var IntConstraint */
protected $lotCount; protected $lotCount;
/** @var NumberConstraint */
protected $amountSum;
/** @var BooleanConstraint */ /** @var BooleanConstraint */
protected $lotNeedsRefill; protected $lotNeedsRefill;
@ -127,7 +129,12 @@ class PartFilter implements FilterInterface
$this->addedDate = new DateTimeConstraint('part.addedDate'); $this->addedDate = new DateTimeConstraint('part.addedDate');
$this->lastModified = new DateTimeConstraint('part.lastModified'); $this->lastModified = new DateTimeConstraint('part.lastModified');
$this->minAmount = new NumberConstraint('part.minAmount'); $this->minAmount = new NumberConstraint('part.minamount');
/* We have to use an IntConstraint here because otherwise we get just an empty result list when applying the filter
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
*/
$this->amountSum = new IntConstraint('amountSum');
$this->lotCount = new IntConstraint('COUNT(partLots)'); $this->lotCount = new IntConstraint('COUNT(partLots)');
$this->supplier = new EntityConstraint($nodesListBuilder, Supplier::class, 'orderdetails.supplier'); $this->supplier = new EntityConstraint($nodesListBuilder, Supplier::class, 'orderdetails.supplier');
$this->lotNeedsRefill = new BooleanConstraint('partLots.needs_refill'); $this->lotNeedsRefill = new BooleanConstraint('partLots.needs_refill');
@ -360,6 +367,10 @@ class PartFilter implements FilterInterface
return $this->manufacturing_status; return $this->manufacturing_status;
} }
public function getAmountSum(): NumberConstraint
{
return $this->amountSum;
}
} }

View file

@ -53,6 +53,7 @@ use App\Entity\Parts\Category;
use App\Entity\Parts\Footprint; use App\Entity\Parts\Footprint;
use App\Entity\Parts\Manufacturer; use App\Entity\Parts\Manufacturer;
use App\Entity\Parts\Part; use App\Entity\Parts\Part;
use App\Entity\Parts\PartLot;
use App\Entity\Parts\Storelocation; use App\Entity\Parts\Storelocation;
use App\Entity\Parts\Supplier; use App\Entity\Parts\Supplier;
use App\Services\AmountFormatter; use App\Services\AmountFormatter;
@ -232,6 +233,7 @@ final class PartsDataTable implements DataTableTypeInterface
return $this->amountFormatter->format($amount, $context->getPartUnit()); return $this->amountFormatter->format($amount, $context->getPartUnit());
}, },
'orderField' => 'amountSum'
]) ])
->add('minamount', TextColumn::class, [ ->add('minamount', TextColumn::class, [
'label' => $this->translator->trans('part.table.minamount'), 'label' => $this->translator->trans('part.table.minamount'),
@ -326,6 +328,7 @@ final class PartsDataTable implements DataTableTypeInterface
private function getQuery(QueryBuilder $builder): void private function getQuery(QueryBuilder $builder): void
{ {
$builder->distinct()->select('part') $builder->distinct()->select('part')
->addSelect('category') ->addSelect('category')
->addSelect('footprint') ->addSelect('footprint')
@ -337,6 +340,16 @@ final class PartsDataTable implements DataTableTypeInterface
->addSelect('orderdetails') ->addSelect('orderdetails')
->addSelect('attachments') ->addSelect('attachments')
->addSelect('storelocations') ->addSelect('storelocations')
//Calculate amount sum using a subquery, so we can filter and sort by it
->addSelect(
'(
SELECT IFNULL(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())
) AS HIDDEN amountSum'
)
->from(Part::class, 'part') ->from(Part::class, 'part')
->leftJoin('part.category', 'category') ->leftJoin('part.category', 'category')
->leftJoin('part.master_picture_attachment', 'master_picture_attachment') ->leftJoin('part.master_picture_attachment', 'master_picture_attachment')

View file

@ -173,6 +173,11 @@ class PartFilterType extends AbstractType
'step' => 1, 'step' => 1,
]); ]);
$builder->add('amountSum', NumberConstraintType::class, [
'label' => 'part.filter.amount_sum',
'min' => 0,
]);
$builder->add('lotNeedsRefill', BooleanConstraintType::class, [ $builder->add('lotNeedsRefill', BooleanConstraintType::class, [
'label' => 'part.filter.lotNeedsRefill' 'label' => 'part.filter.lotNeedsRefill'
]); ]);

View file

@ -54,6 +54,7 @@
<div class="tab-pane pt-3" id="filter-stocks" role="tabpanel" aria-labelledby="filter-stocks-tab" tabindex="0"> <div class="tab-pane pt-3" id="filter-stocks" role="tabpanel" aria-labelledby="filter-stocks-tab" tabindex="0">
{{ form_row(filterForm.storelocation) }} {{ form_row(filterForm.storelocation) }}
{{ form_row(filterForm.minAmount) }} {{ form_row(filterForm.minAmount) }}
{{ form_row(filterForm.amountSum) }}
{{ form_row(filterForm.lotCount) }} {{ form_row(filterForm.lotCount) }}
{{ form_row(filterForm.lotExpirationDate) }} {{ form_row(filterForm.lotExpirationDate) }}
{{ form_row(filterForm.lotNeedsRefill) }} {{ form_row(filterForm.lotNeedsRefill) }}

View file

@ -9513,5 +9513,11 @@ Element 3</target>
<target>None of</target> <target>None of</target>
</segment> </segment>
</unit> </unit>
<unit id="ZnYcxRf" name="part.filter.amount_sum">
<segment>
<source>part.filter.amount_sum</source>
<target>Total amount</target>
</segment>
</unit>
</file> </file>
</xliff> </xliff>