Skip to content

Commit d67e930

Browse files
author
Marcel Diegelmann
committed
Statistik-Bereich um Tab für Projekte/Baugruppen erweitern
1 parent 74513b7 commit d67e930

18 files changed

+754
-1
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { Controller } from '@hotwired/stimulus';
2+
3+
export default class extends Controller {
4+
static values = {
5+
url: String,
6+
confirmMsg: String,
7+
successMsg: String,
8+
errorMsg: String
9+
}
10+
11+
static targets = ["count"]
12+
13+
async cleanup(event) {
14+
event.preventDefault();
15+
16+
if (!confirm(this.confirmMsgValue)) {
17+
return;
18+
}
19+
20+
try {
21+
const response = await fetch(this.urlValue, {
22+
method: 'POST',
23+
headers: {
24+
'X-Requested-With': 'XMLHttpRequest'
25+
}
26+
});
27+
28+
if (response.ok) {
29+
const data = await response.json();
30+
alert(this.successMsgValue.replace('%count%', data.count));
31+
// Update the count displayed in the UI
32+
if (this.hasCountTarget) {
33+
this.countTarget.innerText = '0';
34+
}
35+
// Reload page to reflect changes if needed, or just let the user see 0
36+
window.location.reload();
37+
} else {
38+
alert(this.errorMsgValue);
39+
}
40+
} catch (error) {
41+
console.error('Cleanup failed:', error);
42+
alert(this.errorMsgValue);
43+
}
44+
}
45+
}

src/Controller/StatisticsController.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@
4242
namespace App\Controller;
4343

4444
use App\Services\Tools\StatisticsHelper;
45+
use App\Entity\AssemblySystem\AssemblyBOMEntry;
46+
use Doctrine\ORM\EntityManagerInterface;
4547
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
48+
use Symfony\Component\HttpFoundation\JsonResponse;
4649
use Symfony\Component\HttpFoundation\Response;
4750
use Symfony\Component\Routing\Attribute\Route;
4851

@@ -57,4 +60,33 @@ public function showStatistics(StatisticsHelper $helper): Response
5760
'helper' => $helper,
5861
]);
5962
}
63+
64+
#[Route(path: '/statistics/cleanup-assembly-bom-entries', name: 'statistics_cleanup_assembly_bom_entries', methods: ['POST'])]
65+
public function cleanupAssemblyBOMEntries(EntityManagerInterface $em): JsonResponse
66+
{
67+
$this->denyAccessUnlessGranted('@tools.statistics');
68+
69+
$qb = $em->createQueryBuilder();
70+
$qb->select('be', 'IDENTITY(be.part) AS part_id')
71+
->from(AssemblyBOMEntry::class, 'be')
72+
->leftJoin('be.part', 'p')
73+
->where('be.part IS NOT NULL')
74+
->andWhere('p.id IS NULL');
75+
76+
$results = $qb->getQuery()->getResult();
77+
$count = count($results);
78+
79+
foreach ($results as $result) {
80+
/** @var AssemblyBOMEntry $entry */
81+
$entry = $result[0];
82+
$part_id = $result['part_id'] ?? 'unknown';
83+
84+
$entry->setPart(null);
85+
$entry->setName(sprintf('part-id=%s not found', $part_id));
86+
}
87+
88+
$em->flush();
89+
90+
return new JsonResponse(['success' => true, 'count' => $count]);
91+
}
6092
}

src/Services/Tools/StatisticsHelper.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@
4141

4242
namespace App\Services\Tools;
4343

44+
use App\Entity\AssemblySystem\AssemblyBOMEntry;
4445
use App\Entity\Attachments\Attachment;
4546
use App\Entity\Attachments\AttachmentType;
47+
use App\Entity\AssemblySystem\Assembly;
4648
use App\Entity\ProjectSystem\Project;
4749
use App\Entity\Parts\Category;
4850
use App\Entity\Parts\Footprint;
@@ -79,6 +81,14 @@ public function getDistinctPartsCount(): int
7981
return $this->part_repo->count([]);
8082
}
8183

84+
/**
85+
* Returns the count of distinct projects.
86+
*/
87+
public function getDistinctProjectsCount(): int
88+
{
89+
return $this->em->getRepository(Project::class)->count([]);
90+
}
91+
8292
/**
8393
* Returns the summed instocked over all parts (only parts without a measurement unit).
8494
*
@@ -116,6 +126,7 @@ public function getDataStructuresCount(string $type): int
116126
'storelocation' => StorageLocation::class,
117127
'supplier' => Supplier::class,
118128
'currency' => Currency::class,
129+
'assembly' => Assembly::class,
119130
];
120131

121132
if (!isset($arr[$type])) {
@@ -164,4 +175,19 @@ public function getUserUploadedAttachmentsCount(): int
164175
{
165176
return $this->attachment_repo->getUserUploadedAttachments();
166177
}
178+
179+
/**
180+
* Returns the count of BOM entries which point to a non-existent part ID.
181+
*/
182+
public function getInvalidPartBOMEntriesCount(): int
183+
{
184+
$qb = $this->em->createQueryBuilder();
185+
$qb->select('COUNT(be.id)')
186+
->from(AssemblyBOMEntry::class, 'be')
187+
->leftJoin('be.part', 'p')
188+
->where('be.part IS NOT NULL')
189+
->andWhere('p.id IS NULL');
190+
191+
return (int) $qb->getQuery()->getSingleScalarResult();
192+
}
167193
}

templates/tools/statistics/statistics.html.twig

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@
1414
{% trans %}statistics.parts{% endtrans %}
1515
</a>
1616
</li>
17+
<li class="nav-item">
18+
<a class="nav-link" id="assemblies-tab" data-bs-toggle="tab" href="#assemblies" role="tab" aria-controls="assemblies" aria-selected="false">
19+
{% trans %}statistics.assemblies{% endtrans %}
20+
</a>
21+
</li>
22+
<li class="nav-item">
23+
<a class="nav-link" id="projects-tab" data-bs-toggle="tab" href="#projects" role="tab" aria-controls="projects" aria-selected="false">
24+
{% trans %}statistics.projects{% endtrans %}
25+
</a>
26+
</li>
1727
<li class="nav-item">
1828
<a class="nav-link" id="data_structures-tab" data-bs-toggle="tab" href="#data_structures" role="tab" aria-controls="profile" aria-selected="false">
1929
{% trans %}statistics.data_structures{% endtrans %}
@@ -52,6 +62,58 @@
5262
</table>
5363
</div>
5464

65+
<div class="tab-pane fade" id="assemblies" role="tabpanel" aria-labelledby="assemblies-tab"
66+
{{ stimulus_controller('pages/statistics_assembly', {
67+
url: path('statistics_cleanup_assembly_bom_entries'),
68+
confirmMsg: 'statistics.cleanup_assembly_bom_entries.confirm'|trans,
69+
successMsg: 'statistics.cleanup_assembly_bom_entries.success'|trans,
70+
errorMsg: 'statistics.cleanup_assembly_bom_entries.error'|trans
71+
}) }}
72+
>
73+
<table class="table table-striped table-hover">
74+
<thead>
75+
<tr>
76+
<th>{% trans %}statistics.property{% endtrans %}</th>
77+
<th>{% trans %}statistics.value{% endtrans %}</th>
78+
</tr>
79+
</thead>
80+
<tbody>
81+
<tr>
82+
<td>{% trans %}statistics.distinct_assemblies_count{% endtrans %}</td>
83+
<td>{{ helper.dataStructuresCount("assembly") }}</td>
84+
</tr>
85+
<tr>
86+
<td>{% trans %}statistics.invalid_part_bom_entries_count{% endtrans %}</td>
87+
<td>
88+
<span {{ stimulus_target('pages/statistics_assembly', 'count') }}>{{ helper.invalidPartBOMEntriesCount }}</span>
89+
{% if helper.invalidPartBOMEntriesCount > 0 %}
90+
<button class="btn btn-sm btn-outline-danger ms-2" {{ stimulus_action('pages/statistics_assembly', 'cleanup') }}>
91+
<i class="fas fa-magic"></i> {% trans %}statistics.cleanup_assembly_bom_entries.button{% endtrans %}
92+
</button>
93+
{% endif %}
94+
</td>
95+
</tr>
96+
</tbody>
97+
</table>
98+
</div>
99+
100+
<div class="tab-pane fade" id="projects" role="tabpanel" aria-labelledby="projects-tab">
101+
<table class="table table-striped table-hover">
102+
<thead>
103+
<tr>
104+
<th>{% trans %}statistics.property{% endtrans %}</th>
105+
<th>{% trans %}statistics.value{% endtrans %}</th>
106+
</tr>
107+
</thead>
108+
<tbody>
109+
<tr>
110+
<td>{% trans %}statistics.distinct_projects_count{% endtrans %}</td>
111+
<td>{{ helper.distinctProjectsCount }}</td>
112+
</tr>
113+
</tbody>
114+
</table>
115+
</div>
116+
55117
<div class="tab-pane fade" id="data_structures" role="tabpanel" aria-labelledby="data_structures-tab">
56118
<table class="table table-striped table-hover">
57119
<thead>
@@ -131,4 +193,4 @@
131193
</table>
132194
</div>
133195
</div>
134-
{% endblock %}
196+
{% endblock %}

translations/messages.cs.xlf

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1845,6 +1845,48 @@ Související prvky budou přesunuty nahoru.</target>
18451845
<target>Projekty</target>
18461846
</segment>
18471847
</unit>
1848+
<unit id="stats_cleanup_bom_error" name="statistics.cleanup_assembly_bom_entries.error">
1849+
<segment state="translated">
1850+
<source>statistics.cleanup_assembly_bom_entries.error</source>
1851+
<target>Při čištění došlo k chybě.</target>
1852+
</segment>
1853+
</unit>
1854+
<unit id="stats_cleanup_bom_success" name="statistics.cleanup_assembly_bom_entries.success">
1855+
<segment state="translated">
1856+
<source>statistics.cleanup_assembly_bom_entries.success</source>
1857+
<target>%count% položek bylo úspěšně vyčištěno.</target>
1858+
</segment>
1859+
</unit>
1860+
<unit id="stats_cleanup_bom_confirm" name="statistics.cleanup_assembly_bom_entries.confirm">
1861+
<segment state="translated">
1862+
<source>statistics.cleanup_assembly_bom_entries.confirm</source>
1863+
<target>Chcete vyčistit všechny neplatné položky kusovníku? Odkaz na díl bude odstraněn a název nastaven na "part-id=id not found".</target>
1864+
</segment>
1865+
</unit>
1866+
<unit id="stats_cleanup_bom_btn" name="statistics.cleanup_assembly_bom_entries.button">
1867+
<segment state="translated">
1868+
<source>statistics.cleanup_assembly_bom_entries.button</source>
1869+
<target>Vyčistit</target>
1870+
</segment>
1871+
</unit>
1872+
<unit id="stats_invalid_bom_count" name="statistics.invalid_part_bom_entries_count">
1873+
<segment state="translated">
1874+
<source>statistics.invalid_part_bom_entries_count</source>
1875+
<target>Neplatné položky kusovníku (díl nenalezen)</target>
1876+
</segment>
1877+
</unit>
1878+
<unit id="statistics.distinct_projects_count" name="statistics.distinct_projects_count">
1879+
<segment state="translated">
1880+
<source>statistics.distinct_projects_count</source>
1881+
<target>Počet [[Project]]</target>
1882+
</segment>
1883+
</unit>
1884+
<unit id="stats_assemblies_count" name="statistics.distinct_assemblies_count">
1885+
<segment state="translated">
1886+
<source>statistics.distinct_assemblies_count</source>
1887+
<target>Počet [[Assembly]]</target>
1888+
</segment>
1889+
</unit>
18481890
<unit id="bd7zT1d" name="statistics.assemblies">
18491891
<segment state="translated">
18501892
<source>statistics.assemblies</source>

translations/messages.da.xlf

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1803,6 +1803,48 @@ Underelementer vil blive flyttet opad.</target>
18031803
<target>Projekter</target>
18041804
</segment>
18051805
</unit>
1806+
<unit id="stats_cleanup_bom_error" name="statistics.cleanup_assembly_bom_entries.error">
1807+
<segment state="translated">
1808+
<source>statistics.cleanup_assembly_bom_entries.error</source>
1809+
<target>Der opstod en fejl under oprydningen.</target>
1810+
</segment>
1811+
</unit>
1812+
<unit id="stats_cleanup_bom_success" name="statistics.cleanup_assembly_bom_entries.success">
1813+
<segment state="translated">
1814+
<source>statistics.cleanup_assembly_bom_entries.success</source>
1815+
<target>%count% poster blev ryddet op.</target>
1816+
</segment>
1817+
</unit>
1818+
<unit id="stats_cleanup_bom_confirm" name="statistics.cleanup_assembly_bom_entries.confirm">
1819+
<segment state="translated">
1820+
<source>statistics.cleanup_assembly_bom_entries.confirm</source>
1821+
<target>Vil du rydde op i alle ugyldige stykliste-poster? Forbindelsen til delen vil blive slettet, og navnet sat til "part-id=id not found".</target>
1822+
</segment>
1823+
</unit>
1824+
<unit id="stats_cleanup_bom_btn" name="statistics.cleanup_assembly_bom_entries.button">
1825+
<segment state="translated">
1826+
<source>statistics.cleanup_assembly_bom_entries.button</source>
1827+
<target>Ryd op</target>
1828+
</segment>
1829+
</unit>
1830+
<unit id="stats_invalid_bom_count" name="statistics.invalid_part_bom_entries_count">
1831+
<segment state="translated">
1832+
<source>statistics.invalid_part_bom_entries_count</source>
1833+
<target>Ugyldige stykliste-poster (del ikke fundet)</target>
1834+
</segment>
1835+
</unit>
1836+
<unit id="statistics.distinct_projects_count" name="statistics.distinct_projects_count">
1837+
<segment state="translated">
1838+
<source>statistics.distinct_projects_count</source>
1839+
<target>Antal [[Project]]</target>
1840+
</segment>
1841+
</unit>
1842+
<unit id="stats_assemblies_count" name="statistics.distinct_assemblies_count">
1843+
<segment state="translated">
1844+
<source>statistics.distinct_assemblies_count</source>
1845+
<target>Antal [[Assembly]]</target>
1846+
</segment>
1847+
</unit>
18061848
<unit id="bd7zT1d" name="statistics.assemblies">
18071849
<segment state="translated">
18081850
<source>statistics.assemblies</source>

translations/messages.de.xlf

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1808,6 +1808,48 @@ Subelemente werden beim Löschen nach oben verschoben.</target>
18081808
<target>Projekte</target>
18091809
</segment>
18101810
</unit>
1811+
<unit id="stats_assemblies_count" name="statistics.distinct_assemblies_count">
1812+
<segment state="translated">
1813+
<source>statistics.distinct_assemblies_count</source>
1814+
<target>Anzahl [[Assembly]]</target>
1815+
</segment>
1816+
</unit>
1817+
<unit id="statistics.distinct_projects_count" name="statistics.distinct_projects_count">
1818+
<segment state="translated">
1819+
<source>statistics.distinct_projects_count</source>
1820+
<target>Anzahl [[Project]]</target>
1821+
</segment>
1822+
</unit>
1823+
<unit id="stats_invalid_bom_count" name="statistics.invalid_part_bom_entries_count">
1824+
<segment state="translated">
1825+
<source>statistics.invalid_part_bom_entries_count</source>
1826+
<target>Ungültige Stücklisteneinträge (Teil nicht gefunden)</target>
1827+
</segment>
1828+
</unit>
1829+
<unit id="stats_cleanup_bom_btn" name="statistics.cleanup_assembly_bom_entries.button">
1830+
<segment state="translated">
1831+
<source>statistics.cleanup_assembly_bom_entries.button</source>
1832+
<target>Bereinigen</target>
1833+
</segment>
1834+
</unit>
1835+
<unit id="stats_cleanup_bom_confirm" name="statistics.cleanup_assembly_bom_entries.confirm">
1836+
<segment state="translated">
1837+
<source>statistics.cleanup_assembly_bom_entries.confirm</source>
1838+
<target>Möchten Sie alle ungültigen Stücklisteneinträge bereinigen? Die Verknüpfung zum Teil wird gelöscht und der Name auf "part-id=id not found" gesetzt.</target>
1839+
</segment>
1840+
</unit>
1841+
<unit id="stats_cleanup_bom_success" name="statistics.cleanup_assembly_bom_entries.success">
1842+
<segment state="translated">
1843+
<source>statistics.cleanup_assembly_bom_entries.success</source>
1844+
<target>%count% Einträge wurden erfolgreich bereinigt.</target>
1845+
</segment>
1846+
</unit>
1847+
<unit id="stats_cleanup_bom_error" name="statistics.cleanup_assembly_bom_entries.error">
1848+
<segment state="translated">
1849+
<source>statistics.cleanup_assembly_bom_entries.error</source>
1850+
<target>Bei der Bereinigung ist ein Fehler aufgetreten.</target>
1851+
</segment>
1852+
</unit>
18111853
<unit id="a2idAxu" name="statistics.data_structures">
18121854
<notes>
18131855
<note priority="1">new</note>

0 commit comments

Comments
 (0)