From fa7cedd2fe01ed7eb3c9f674b86982a61f86b293 Mon Sep 17 00:00:00 2001 From: Whinis Date: Tue, 3 Feb 2026 23:22:09 -0500 Subject: [PATCH 1/2] Added Price and Extended price to project bom table. --- src/DataTables/ProjectBomEntriesDataTable.php | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/DataTables/ProjectBomEntriesDataTable.php b/src/DataTables/ProjectBomEntriesDataTable.php index 433f6f78b..3acef03f5 100644 --- a/src/DataTables/ProjectBomEntriesDataTable.php +++ b/src/DataTables/ProjectBomEntriesDataTable.php @@ -39,6 +39,7 @@ use Omines\DataTablesBundle\DataTable; use Omines\DataTablesBundle\DataTableTypeInterface; use Symfony\Contracts\Translation\TranslatorInterface; +use Brick\Math\BigDecimal; class ProjectBomEntriesDataTable implements DataTableTypeInterface { @@ -179,6 +180,67 @@ public function configure(DataTable $dataTable, array $options): void return ''; } ]) + ->add('price', TextColumn::class, [ + 'label' => 'project.bom.price', + 'render' => function ($value, ProjectBOMEntry $context) { + // Let's attempt to get the part, if we don't we will just assume zero + $part = $context->getPart(); + $price = BigDecimal::zero(); + $pricedetails = null; + $order = null; + // Check if we get a part and get the first order if so + // if not see if there is a non-part price set + if($part) { + $order = $context->getPart()->getOrderdetails()->first(); + } else if($context->getPrice() !== null) { + $price = $context->getPrice(); + } + + // check if there is an order, if so get the first pricedetail of the order + if($order!==null && $order !== false) { + $pricedetails = $order->getPricedetails()->first(); + } + + // check if there is a pricedetail, if so get the first price + if($pricedetails !== null && $pricedetails !== false) { + $price = $pricedetails->getPrice(); + } + + // return the price + return htmlspecialchars(number_format($price->toFloat(),2)); + }, + 'visible' => false, + ]) + ->add('ext_price', TextColumn::class, [ + 'label' => 'project.bom.ext_price', + 'render' => function ($value, ProjectBOMEntry $context) { + // Let's attempt to get the part, if we don't we will just assume zero + $part = $context->getPart(); + $price = BigDecimal::zero(); + $pricedetails = null; + $order = null; + // Check if we get a part and get the first order if so + // if not see if there is a non-part price set + if($part) { + $order = $context->getPart()->getOrderdetails()->first(); + } else if($context->getPrice() !== null) { + $price = $context->getPrice(); + } + + // check if there is an order, if so get the first pricedetail of the order + if($order!==null && $order !== false) { + $pricedetails = $order->getPricedetails()->first(); + } + + // check if there is a pricedetail, if so get the first price + if($pricedetails !== null && $pricedetails !== false) { + $price = $pricedetails->getPrice(); + } + + // return the price + return htmlspecialchars(number_format($price->toFloat() * $context->getQuantity(),2)); + }, + ]) ->add('addedDate', LocaleDateTimeColumn::class, [ 'label' => $this->translator->trans('part.table.addedDate'), From d6cf425ec59bed1b46182d0ddc7a039094077fd8 Mon Sep 17 00:00:00 2001 From: Whinis Date: Fri, 13 Mar 2026 16:34:42 -0400 Subject: [PATCH 2/2] Made changes from MayNiklas proposed by jbtronics --- src/DataTables/ProjectBomEntriesDataTable.php | 58 +++++-------------- 1 file changed, 13 insertions(+), 45 deletions(-) diff --git a/src/DataTables/ProjectBomEntriesDataTable.php b/src/DataTables/ProjectBomEntriesDataTable.php index 3acef03f5..7bfa8a03d 100644 --- a/src/DataTables/ProjectBomEntriesDataTable.php +++ b/src/DataTables/ProjectBomEntriesDataTable.php @@ -32,6 +32,7 @@ use App\Services\ElementTypeNameGenerator; use App\Services\EntityURLGenerator; use App\Services\Formatters\AmountFormatter; +use App\Services\Parts\PricedetailHelper; use Doctrine\ORM\QueryBuilder; use Omines\DataTablesBundle\Adapter\Doctrine\ORM\SearchCriteriaProvider; use Omines\DataTablesBundle\Adapter\Doctrine\ORMAdapter; @@ -44,7 +45,8 @@ class ProjectBomEntriesDataTable implements DataTableTypeInterface { public function __construct(protected TranslatorInterface $translator, protected PartDataTableHelper $partDataTableHelper, - protected EntityURLGenerator $entityURLGenerator, protected AmountFormatter $amountFormatter) + protected EntityURLGenerator $entityURLGenerator, protected AmountFormatter $amountFormatter, + protected PricedetailHelper $pricedetailHelper) { } @@ -183,28 +185,7 @@ public function configure(DataTable $dataTable, array $options): void ->add('price', TextColumn::class, [ 'label' => 'project.bom.price', 'render' => function ($value, ProjectBOMEntry $context) { - // Let's attempt to get the part, if we don't we will just assume zero - $part = $context->getPart(); - $price = BigDecimal::zero(); - $pricedetails = null; - $order = null; - // Check if we get a part and get the first order if so - // if not see if there is a non-part price set - if($part) { - $order = $context->getPart()->getOrderdetails()->first(); - } else if($context->getPrice() !== null) { - $price = $context->getPrice(); - } - - // check if there is an order, if so get the first pricedetail of the order - if($order!==null && $order !== false) { - $pricedetails = $order->getPricedetails()->first(); - } - - // check if there is a pricedetail, if so get the first price - if($pricedetails !== null && $pricedetails !== false) { - $price = $pricedetails->getPrice(); - } + $price = $this->getBomEntryUnitPrice($context); // return the price return htmlspecialchars(number_format($price->toFloat(),2)); @@ -214,28 +195,7 @@ public function configure(DataTable $dataTable, array $options): void ->add('ext_price', TextColumn::class, [ 'label' => 'project.bom.ext_price', 'render' => function ($value, ProjectBOMEntry $context) { - // Let's attempt to get the part, if we don't we will just assume zero - $part = $context->getPart(); - $price = BigDecimal::zero(); - $pricedetails = null; - $order = null; - // Check if we get a part and get the first order if so - // if not see if there is a non-part price set - if($part) { - $order = $context->getPart()->getOrderdetails()->first(); - } else if($context->getPrice() !== null) { - $price = $context->getPrice(); - } - - // check if there is an order, if so get the first pricedetail of the order - if($order!==null && $order !== false) { - $pricedetails = $order->getPricedetails()->first(); - } - - // check if there is a pricedetail, if so get the first price - if($pricedetails !== null && $pricedetails !== false) { - $price = $pricedetails->getPrice(); - } + $price = $this->getBomEntryUnitPrice($context); // return the price return htmlspecialchars(number_format($price->toFloat() * $context->getQuantity(),2)); @@ -267,6 +227,14 @@ function (QueryBuilder $builder) use ($options): void { ], ]); } + private function getBomEntryUnitPrice(ProjectBOMEntry $entry): BigDecimal + { + if ($entry->getPart() instanceof Part) { + return $this->pricedetailHelper->calculateAvgPrice($entry->getPart(), $entry->getQuantity()) ?? BigDecimal::zero(); + } + + return $entry->getPrice() ?? BigDecimal::zero(); + } private function getQuery(QueryBuilder $builder, array $options): void {