Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions migrations/Version20240905085300.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

namespace DoctrineMigrations;

use App\Migration\AbstractMultiPlatformMigration;
use Doctrine\DBAL\Schema\Schema;

final class Version20240905085300 extends AbstractMultiPlatformMigration
{
public function getDescription(): string
{
return 'Added order fields';
}

public function mySQLUp(Schema $schema): void
{
$this->addSql('ALTER TABLE parts ADD orderamount DOUBLE PRECISION NOT NULL DEFAULT 0, ADD orderDelivery DATETIME');
}

public function mySQLDown(Schema $schema): void
{
$this->addSql('ALTER TABLE `parts` DROP orderamount, DROP orderDelivery');
}

public function postgreSQLUp(Schema $schema): void
{
$this->addSql('ALTER TABLE parts ADD orderamount DOUBLE PRECISION NOT NULL DEFAULT 0, ADD orderDelivery timestamp');
}

public function postgreSQLDown(Schema $schema): void
{
$this->addSql('ALTER TABLE parts DROP orderamount, DROP orderDelivery');
}

public function sqLiteUp(Schema $schema): void
{
$this->addSql('ALTER TABLE parts ADD COLUMN orderamount DOUBLE PRECISION NOT NULL DEFAULT 0');
$this->addSql('ALTER TABLE parts ADD COLUMN orderDelivery DATETIME');
}

public function sqLiteDown(Schema $schema): void
{
$error;
// TODO: implement backwards migration for SQlite
}
}
2 changes: 1 addition & 1 deletion public/kicad/footprints.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated on Mon Jun 8 06:51:27 UTC 2026
# Generated on Mon Jun 15 07:28:00 UTC 2026
# This file contains all footprints available in the offical KiCAD library
Audio_Module:Reverb_BTDR-1H
Audio_Module:Reverb_BTDR-1V
Expand Down
39 changes: 37 additions & 2 deletions public/kicad/symbols.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated on Mon Jun 8 06:52:04 UTC 2026
# Generated on Mon Jun 15 07:28:38 UTC 2026
# This file contains all symbols available in the offical KiCAD library
4xxx:14528
4xxx:14529
Expand Down Expand Up @@ -5300,21 +5300,39 @@ Converter_DCDC:TMR-4812
Converter_DCDC:TMR-4821
Converter_DCDC:TMR-4822
Converter_DCDC:TMR-4823
Converter_DCDC:TMR10-1211WI
Converter_DCDC:TMR10-1212WI
Converter_DCDC:TMR10-1213WI
Converter_DCDC:TMR10-1215WI
Converter_DCDC:TMR10-1222WI
Converter_DCDC:TMR10-1223WI
Converter_DCDC:TMR10-2410WIR
Converter_DCDC:TMR10-2411WI
Converter_DCDC:TMR10-2411WIR
Converter_DCDC:TMR10-2412WI
Converter_DCDC:TMR10-2412WIR
Converter_DCDC:TMR10-2413WI
Converter_DCDC:TMR10-2413WIR
Converter_DCDC:TMR10-2415WI
Converter_DCDC:TMR10-2415WIR
Converter_DCDC:TMR10-2421WIR
Converter_DCDC:TMR10-2422WI
Converter_DCDC:TMR10-2422WIR
Converter_DCDC:TMR10-2423WI
Converter_DCDC:TMR10-2423WIR
Converter_DCDC:TMR10-4810WIR
Converter_DCDC:TMR10-4811WI
Converter_DCDC:TMR10-4811WIR
Converter_DCDC:TMR10-4812WI
Converter_DCDC:TMR10-4812WIR
Converter_DCDC:TMR10-4813WI
Converter_DCDC:TMR10-4813WIR
Converter_DCDC:TMR10-4815WI
Converter_DCDC:TMR10-4815WIR
Converter_DCDC:TMR10-4821WIR
Converter_DCDC:TMR10-4822WI
Converter_DCDC:TMR10-4822WIR
Converter_DCDC:TMR10-4823WI
Converter_DCDC:TMR10-4823WIR
Converter_DCDC:TMR10-7210WIR
Converter_DCDC:TMR10-7211WIR
Expand Down Expand Up @@ -14593,6 +14611,8 @@ MCU_Texas:LM4F111C4QR
MCU_Texas:LM4F111E5QR
MCU_Texas:LM4F111H5QR
MCU_Texas:MSP432E401Y
MCU_Texas:MSPM0C110xSDDF
MCU_Texas:MSPM0C110xSDSG
MCU_Texas:TM4C1230C3PM
MCU_Texas:TM4C1230D5PM
MCU_Texas:TM4C1230E6PM
Expand Down Expand Up @@ -15671,6 +15691,7 @@ Power_Management:LM5069MM-1
Power_Management:LM5069MM-2
Power_Management:LM66100DCK
Power_Management:LM74700
Power_Management:LM74701-Q1
Power_Management:LMG3410
Power_Management:LMG5200
Power_Management:LT1641-1
Expand Down Expand Up @@ -15772,6 +15793,7 @@ Power_Management:TPS22810DBV
Power_Management:TPS22810DRV
Power_Management:TPS22917DBV
Power_Management:TPS22917LDBV
Power_Management:TPS22919DCK
Power_Management:TPS22929D
Power_Management:TPS22993
Power_Management:TPS2412D
Expand Down Expand Up @@ -16683,6 +16705,19 @@ Reference_Voltage:LM4040LP-4.1
Reference_Voltage:LM4040LP-5
Reference_Voltage:LM4040LP-8.2
Reference_Voltage:LM4041LP-ADJ
Reference_Voltage:LM4050xEM3-2.1
Reference_Voltage:LM4050xEM3-2.5
Reference_Voltage:LM4050xEM3-3.0
Reference_Voltage:LM4050xEM3-3.3
Reference_Voltage:LM4050xEM3-4.1
Reference_Voltage:LM4050xEM3-5.0
Reference_Voltage:LM4050xEX3-2.1
Reference_Voltage:LM4050xEX3-2.5
Reference_Voltage:LM4050xEX3-3.3
Reference_Voltage:LM4050xEX3-4.1
Reference_Voltage:LM4050xEX3-5.0
Reference_Voltage:LM4051xEM3-1.2
Reference_Voltage:LM4051xEX3-1.2
Reference_Voltage:LM4125AIM5-2.5
Reference_Voltage:LM4125IM5-2.0
Reference_Voltage:LM4125IM5-2.5
Expand Down Expand Up @@ -16830,7 +16865,6 @@ Reference_Voltage:MCP1501-25xCH
Reference_Voltage:MCP1501-25xRW
Reference_Voltage:MCP1501-25xSN
Reference_Voltage:MCP1501-30xCH
Reference_Voltage:MCP1501-30xRW
Reference_Voltage:MCP1501-30xSN
Reference_Voltage:MCP1501-33xCH
Reference_Voltage:MCP1501-33xRW
Expand Down Expand Up @@ -20991,6 +21025,7 @@ Sensor_Temperature:MCP9501
Sensor_Temperature:MCP9502
Sensor_Temperature:MCP9503
Sensor_Temperature:MCP9504
Sensor_Temperature:MCP96xx01x-x-MX
Sensor_Temperature:MCP9700Ax-ELT
Sensor_Temperature:MCP9700Ax-ETT
Sensor_Temperature:MCP9700Ax-HLT
Expand Down
21 changes: 21 additions & 0 deletions src/Controller/PartController.php
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,27 @@ public function markBulkImportComplete(Part $part, int $jobId, Request $request)
return $this->redirectToRoute('bulk_info_provider_step2', ['jobId' => $jobId]);
}

#[Route(path: '/{id}/delivered', name: 'part_delivered')]
public function delivered(Part $part, Request $request): Response
{
$this->denyAccessUnlessGranted('edit', $part);

$partLot = $part->getPartLots()[0] ?? null;
if (!$partLot instanceof PartLot) {
$this->addFlash('error', 'part.delivered.error.no_lot');
return $this->redirectToRoute('part_info', ['id' => $part->getID()]);
}

$partLot->setAmount($partLot->getAmount() + $part->getOrderAmount());
$part->setOrderAmount(0);
$part->setOrderDelivery(null);

$this->em->persist($part);
$this->em->flush();

return $this->redirectToRoute('part_info', ['id' => $part->getID()]);
}

#[Route(path: '/{id}/delete', name: 'part_delete', methods: ['DELETE'])]
public function delete(Request $request, Part $part): RedirectResponse
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class LessThanDesiredConstraint extends BooleanConstraint
public function __construct(?string $property = null, ?string $identifier = null, ?bool $default_value = null)
{
parent::__construct($property ?? '(
SELECT COALESCE(SUM(ld_partLot.amount), 0.0)
SELECT COALESCE(SUM(ld_partLot.amount) + part.orderamount, 0.0)
FROM '.PartLot::class.' ld_partLot
WHERE ld_partLot.part = part.id
AND ld_partLot.instock_unknown = false
Expand All @@ -48,7 +48,7 @@ public function apply(QueryBuilder $queryBuilder): void

//If value is true, we want to filter for parts with stock < desired stock
if ($this->value) {
$queryBuilder->andHaving( $this->property . ' < part.minamount');
$queryBuilder->andHaving($this->property . ' < part.minamount');
} else {
$queryBuilder->andHaving($this->property . ' >= part.minamount');
}
Expand Down
4 changes: 4 additions & 0 deletions src/DataTables/Filters/PartFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ class PartFilter implements FilterInterface
public readonly TextConstraint $comment;
public readonly TagsConstraint $tags;
public readonly NumberConstraint $minAmount;
public readonly NumberConstraint $orderAmount;
public readonly DateTimeConstraint $orderDelivery;
public readonly BooleanConstraint $favorite;
public readonly BooleanConstraint $needsReview;
public readonly NumberConstraint $mass;
Expand Down Expand Up @@ -140,6 +142,8 @@ public function __construct(NodesListBuilder $nodesListBuilder)
$this->lastModified = new DateTimeConstraint('part.lastModified');

$this->minAmount = new NumberConstraint('part.minamount');
$this->orderAmount = new NumberConstraint('part.orderamount');
$this->orderDelivery = new DateTimeConstraint('part.orderDelivery');
/* 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
Expand Down
9 changes: 9 additions & 0 deletions src/DataTables/PartsDataTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,15 @@ public function configure(DataTable $dataTable, array $options): void
$context->getPartUnit()
),
])
->add('orderamount', TextColumn::class, [
'label' => $this->translator->trans('part.table.orderamount'),
'render' => fn($value, Part $context): string => htmlspecialchars($this->amountFormatter->format($value,
$context->getPartUnit())),
])
->add('orderDelivery', LocaleDateTimeColumn::class, [
'label' => $this->translator->trans('part.table.orderDelivery'),
'timeFormat' => 'none',
])
->add('partUnit', TextColumn::class, [
'label' => $this->translator->trans('part.table.partUnit'),
'orderField' => 'NATSORT(_partUnit.name)',
Expand Down
71 changes: 69 additions & 2 deletions src/DataTables/ProjectBomEntriesDataTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public function configure(DataTable $dataTable, array $options): void
])
->add('partId', TextColumn::class, [
'label' => $this->translator->trans('project.bom.part_id'),
'visible' => true,
'visible' => false,
'orderField' => 'part.id',
'data' => function (ProjectBOMEntry $context) {
return $context->getPart() instanceof Part ? (string) $context->getPart()->getId() : '';
Expand Down Expand Up @@ -150,6 +150,7 @@ public function configure(DataTable $dataTable, array $options): void
])
->add('footprint', EntityColumn::class, [
'property' => 'part.footprint',
'visible' => false,
'label' => $this->translator->trans('part.table.footprint'),
'orderField' => 'NATSORT(footprint.name)'
])
Expand All @@ -159,6 +160,39 @@ public function configure(DataTable $dataTable, array $options): void
'label' => $this->translator->trans('part.table.manufacturer'),
'orderField' => 'NATSORT(manufacturer.name)'
])
->add('supplier', HTMLColumn::class, [
'label' => $this->translator->trans('supplier.label'),
'visible' => true,
// Use an aggregate because a part can have multiple supplier orderdetails.
'orderField' => 'NATSORT(MIN(_suppliers.name))',
'data' => function (ProjectBOMEntry $context): string {
if (!$context->getPart() instanceof Part) {
return '';
}

$supplierLinks = [];
foreach ($context->getPart()->getOrderdetails(true) as $orderdetail) {
$supplier = $orderdetail->getSupplier();
$supplierName = trim((string) $supplier->getName());
if ($supplierName === '') {
continue;
}

$supplierId = $supplier->getId();
if (isset($supplierLinks[$supplierId])) {
continue;
}

$supplierLinks[$supplierId] = sprintf(
'<a href="%s">%s</a>',
htmlspecialchars($this->entityURLGenerator->listPartsURL($supplier)),
htmlspecialchars($supplierName)
);
}

return implode(', ', $supplierLinks);
},
])

->add('manufacturing_status', EnumColumn::class, [
'label' => $this->translator->trans('part.table.manufacturingStatus'),
Expand All @@ -176,6 +210,7 @@ public function configure(DataTable $dataTable, array $options): void

->add('mountnames', HTMLColumn::class, [
'label' => 'project.bom.mountnames',
'visible' => false,
'data' => function (ProjectBOMEntry $context) {
$html = '';

Expand All @@ -188,7 +223,7 @@ public function configure(DataTable $dataTable, array $options): void

->add('instockAmount', HTMLColumn::class, [
'label' => 'project.bom.instockAmount',
'visible' => false,
'visible' => true,
'data' => function (ProjectBOMEntry $context) {
if ($context->getPart() !== null) {
return $this->partDataTableHelper->renderAmount($context->getPart());
Expand All @@ -197,6 +232,30 @@ public function configure(DataTable $dataTable, array $options): void
return '';
},
])
->add('minAmount', HTMLColumn::class, [
'label' => $this->translator->trans('part.table.minamount'),
'visible' => true,
'orderField' => 'part.minamount',
'data' => function (ProjectBOMEntry $context): string {
if (!$context->getPart() instanceof Part) {
return '';
}

return $this->amountFormatter->format($context->getPart()->getMinAmount(), $context->getPart()->getPartUnit());
},
])
->add('orderAmount', HTMLColumn::class, [
'label' => $this->translator->trans('part.table.orderamount'),
'visible' => true,
'orderField' => 'part.orderamount',
'data' => function (ProjectBOMEntry $context): string {
if (!$context->getPart() instanceof Part) {
return '';
}

return $this->amountFormatter->format($context->getPart()->getOrderAmount(), $context->getPart()->getPartUnit());
},
])
->add('storelocation', HTMLColumn::class, [
'label' => $this->translator->trans('part.table.storeLocations'),
//We need to use a aggregate function to get the first store location, as we have a one-to-many relation
Expand Down Expand Up @@ -272,6 +331,8 @@ private function getFilterQuery(QueryBuilder $builder, array $options): void
->leftJoin('_partLots.storage_location', '_storelocations')
->leftJoin('part.footprint', 'footprint')
->leftJoin('part.manufacturer', 'manufacturer')
->leftJoin('part.orderdetails', '_orderdetails')
->leftJoin('_orderdetails.supplier', '_suppliers')
->leftJoin('part.partCustomState', 'partCustomState')
->where('bom_entry.project = :project')
->setParameter('project', $options['project'])
Expand Down Expand Up @@ -299,6 +360,8 @@ private function getDetailQuery(QueryBuilder $builder, array $filter_results): v
->addSelect('storelocations')
->addSelect('footprint')
->addSelect('manufacturer')
->addSelect('orderdetails')
->addSelect('suppliers')
->addSelect('partCustomState')
->from(ProjectBOMEntry::class, 'bom_entry')
->leftJoin('bom_entry.part', 'part')
Expand All @@ -307,6 +370,8 @@ private function getDetailQuery(QueryBuilder $builder, array $filter_results): v
->leftJoin('partLots.storage_location', 'storelocations')
->leftJoin('part.footprint', 'footprint')
->leftJoin('part.manufacturer', 'manufacturer')
->leftJoin('part.orderdetails', 'orderdetails')
->leftJoin('orderdetails.supplier', 'suppliers')
->leftJoin('part.partCustomState', 'partCustomState')
->where('bom_entry.id IN (:ids)')
->setParameter('ids', $ids)
Expand All @@ -317,6 +382,8 @@ private function getDetailQuery(QueryBuilder $builder, array $filter_results): v
->addGroupBy('storelocations')
->addGroupBy('footprint')
->addGroupBy('manufacturer')
->addGroupBy('orderdetails')
->addGroupBy('suppliers')
->addGroupBy('partCustomState')

->setHint(Query::HINT_READ_ONLY, true)
Expand Down
Loading