mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2026-08-03 23:21:44 +00:00
Merge b1390b481a into 62f3216071
This commit is contained in:
commit
63a996d0cb
5 changed files with 219 additions and 0 deletions
|
|
@ -163,6 +163,8 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co
|
|||
label: "tools.builtin_footprints_viewer.title"
|
||||
ic_logos:
|
||||
label: "perm.tools.ic_logos"
|
||||
multi_build:
|
||||
label: "tools.multi_build.title"
|
||||
|
||||
info_providers:
|
||||
label: "perm.part.info_providers"
|
||||
|
|
|
|||
|
|
@ -31,9 +31,14 @@ use App\Services\System\GitVersionInfoProvider;
|
|||
use App\Services\System\UpdateAvailableFacade;
|
||||
use App\Settings\AppSettings;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Runtime\SymfonyRuntime;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use App\Entity\ProjectSystem\Project;
|
||||
use App\Form\ProjectSystem\ProjectMultiBuildType;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
#[Route(path: '/tools')]
|
||||
class ToolsController extends AbstractController
|
||||
|
|
@ -122,6 +127,91 @@ class ToolsController extends AbstractController
|
|||
]);
|
||||
}
|
||||
|
||||
#[Route(path: '/multi_build', name: 'tools_multi_build')]
|
||||
public function multiBuild(EntityManagerInterface $entityManager, Request $request): Response
|
||||
{
|
||||
//$this->denyAccessUnlessGranted('@tools.multi_build');
|
||||
$all_projects = $entityManager->getRepository(Project::class)->findAll();
|
||||
|
||||
$form = $this->createForm(ProjectMultiBuildType::class, [], ['projects'=>$all_projects]);
|
||||
|
||||
$form->handleRequest($request);
|
||||
$combined_bom=[];
|
||||
$needs_ordering = [];
|
||||
$can_build = true;
|
||||
$orders_per_supplier = null;
|
||||
if ($form->isSubmitted())
|
||||
{
|
||||
if ($form->isValid())
|
||||
{
|
||||
foreach($all_projects as $p)
|
||||
{
|
||||
$count_for_project = $form->get($p->getID() . "_project")->getData() + 0;
|
||||
if ($count_for_project > 0)
|
||||
{
|
||||
foreach ($p->getBomEntries() as $bom_entry)
|
||||
{
|
||||
if ($bom_entry->getPart())
|
||||
{
|
||||
$part_id = $bom_entry->getPart()->getID();
|
||||
if (array_key_exists($part_id, $combined_bom))
|
||||
{
|
||||
$combined_bom[$part_id]['quantity'] += $bom_entry->getQuantity() * $count_for_project;
|
||||
}
|
||||
else
|
||||
{
|
||||
$combined_bom[$part_id] = array('quantity'=>$bom_entry->getQuantity() * $count_for_project, 'part'=>$bom_entry->getPart());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$orders_per_supplier=[];
|
||||
|
||||
foreach($combined_bom as $cb)
|
||||
{
|
||||
$total_instock = $cb['part']->getAmountSum();
|
||||
if ($total_instock < $cb['quantity'])
|
||||
{
|
||||
$can_build = false;
|
||||
$suppliers = $cb['part']->getOrderDetails();
|
||||
if ($suppliers && count($suppliers) > 0)
|
||||
{
|
||||
$mid = $suppliers[0]->getSupplier()->getID();
|
||||
$orderable_part=array(
|
||||
'part'=>$cb['part'],
|
||||
'pn'=>$suppliers[0]->getSupplierPartNr(),
|
||||
'needed'=>($cb['quantity']-$total_instock),
|
||||
'link'=>$suppliers[0]->getSupplierProductURL());
|
||||
if (array_key_exists($mid, $orders_per_supplier))
|
||||
{
|
||||
$orders_per_supplier[$mid]['items'][] = $orderable_part;
|
||||
}
|
||||
else
|
||||
{
|
||||
$orders_per_supplier[$mid] = array(
|
||||
'supplier'=>$suppliers[0]->getSupplier()->getName(),
|
||||
'items'=>array($orderable_part));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$needs_ordering[] = array('needed'=>($cb['quantity']-$total_instock), 'part'=>$cb['part']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('tools/multi_build/multi_build.html.twig', [
|
||||
'form'=>$form,
|
||||
'needs_ordering'=>$needs_ordering,
|
||||
'can_build'=>$can_build,
|
||||
'orders_per_supplier'=>$orders_per_supplier
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route(path: '/ic_logos', name: 'tools_ic_logos')]
|
||||
public function icLogos(): Response
|
||||
{
|
||||
|
|
|
|||
58
src/Form/ProjectSystem/ProjectMultiBuildType.php
Normal file
58
src/Form/ProjectSystem/ProjectMultiBuildType.php
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
/*
|
||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
||||
*
|
||||
* Copyright (C) 2019 - 2026 Jan Böhmer (https://github.com/jbtronics)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* 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\Form\ProjectSystem;
|
||||
|
||||
use App\Services\InfoProviderSystem\ProviderRegistry;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use App\Entity\ProjectSystem\Project;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class ProjectMultiBuildType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
foreach($options['projects'] as $p)
|
||||
{
|
||||
$builder->add($p->getID() . '_project', NumberType::class, [
|
||||
'label' => $p->getName(),
|
||||
'required' => false,
|
||||
],0);
|
||||
}
|
||||
|
||||
$builder->add('submit', SubmitType::class, [
|
||||
'label' => 'info_providers.search.submit',
|
||||
]);
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'projects' => [],
|
||||
]);
|
||||
$resolver->setAllowedTypes('projects', 'array');
|
||||
}
|
||||
}
|
||||
|
|
@ -131,6 +131,12 @@ class ToolsTreeBuilder
|
|||
$this->urlGenerator->generate('tools_builtin_footprints_viewer')
|
||||
))->setIcon('fa-treeview fa-fw fa-solid fa-images');
|
||||
}
|
||||
if ($this->security->isGranted('@tools.multi_build')) {
|
||||
$nodes[] = (new TreeViewNode(
|
||||
"Multi Build",
|
||||
$this->urlGenerator->generate('tools_multi_build')
|
||||
))->setIcon('fa-treeview fa-fw fa-solid fa-images');
|
||||
}
|
||||
if ($this->security->isGranted('@tools.ic_logos')) {
|
||||
$nodes[] = (new TreeViewNode(
|
||||
$this->translator->trans('perm.tools.ic_logos'),
|
||||
|
|
|
|||
63
templates/tools/multi_build/multi_build.html.twig
Normal file
63
templates/tools/multi_build/multi_build.html.twig
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
{% extends "main_card.html.twig" %}
|
||||
|
||||
{% block title %}Multi Build{% endblock %}
|
||||
|
||||
|
||||
{% block card_title %}<i class="fas fa-chart-bar fa-fw"></i>
|
||||
Multi Build{% endblock %}
|
||||
|
||||
{% block card_body %}
|
||||
|
||||
<div class="alert {% if can_build %}alert-success{% else %}alert-danger{% endif %}" role="alert">
|
||||
{% if not can_build %}
|
||||
<h5><i class="fa-solid fa-circle-exclamation fa-fw"></i>Parts needed without supplier.</h5>
|
||||
<ul>
|
||||
{% for bom_entry in needs_ordering %}
|
||||
<li>
|
||||
<b><a href="{{ entity_url(bom_entry.part) }}">{{ bom_entry.part.name }}</a></b>
|
||||
{{ bom_entry.needed }} Needed.
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if orders_per_supplier is not null %}
|
||||
<table class="table table-striped table-hover">
|
||||
{% for supplier in orders_per_supplier %}
|
||||
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan=7>
|
||||
{% if supplier.supplier is not null %}{{ supplier.supplier }}{% else %}No supplier{% endif %}
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>{% trans %}name.label{% endtrans %}</th>
|
||||
<th>{% trans %}orderdetails.edit.supplierpartnr{% endtrans %}</th>
|
||||
<th>{% trans %}description.label{% endtrans %}</th>
|
||||
<th>Quantity Needed</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
{% for item in supplier.items %}
|
||||
<tr>
|
||||
<td/>
|
||||
<td><a href="{{ entity_url(item.part) }}">{{ item.part.name }}</a></td>
|
||||
<td><a href="{{ item.link }}">{{ item.pn }}</a></td>
|
||||
<td>{{ item.part.description }}</td>
|
||||
<td>{{ item.needed }}</td>
|
||||
<td/>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{{ form(form) }}
|
||||
|
||||
{% endblock %}
|
||||
Loading…
Add table
Add a link
Reference in a new issue