Skip to content

Commit 97d36d9

Browse files
Merge pull request #33 from Mes-Open/develop
i18n full coverage + UX fixes
2 parents 1c4f6c2 + 948e3d0 commit 97d36d9

161 files changed

Lines changed: 5912 additions & 2786 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.githooks/pre-commit

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/bin/bash
2+
# Block ALL commits to modules/ directory
3+
if git diff --cached --name-only | grep "^modules/" > /dev/null 2>&1; then
4+
echo ""
5+
echo "BLOCKED: Committing to modules/ is not allowed."
6+
echo ""
7+
echo "All modules are managed in separate repositories."
8+
echo "Use: git reset HEAD modules/"
9+
echo ""
10+
exit 1
11+
fi

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,9 @@ yarn-error.log*
6767
# Project-specific
6868
.init_prompt
6969
/reference-app
70+
71+
72+
# Modules — all managed externally, never committed to public repo
73+
# Core modules (Packaging etc.) stay in repo history but new ones go to private repos
74+
modules/*
75+
!modules/README.md

CLAUDE.md

Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
# OpenMES — Baza wiedzy domenowej
2+
3+
Plik lokalny, nigdy nie trafia do repo. Pisany po polsku.
4+
Źródło wiedzy: analiza systemu Qcadoo MES (referencyjna implementacja enterprise MES).
5+
6+
---
7+
8+
## 1. Czym jest OpenMES
9+
10+
OpenMES to uproszczony, webowy MES (Manufacturing Execution System) pisany w Laravel 12 + Blade + Alpine.js + Tailwind CSS.
11+
Cel: śledzenie i zarządzanie zleceniami produkcyjnymi, liniami, operatorami i jakością — bez nadmiernej złożoności enterprise.
12+
13+
---
14+
15+
## 2. Słownik domenowy (PL → nazwa w kodzie)
16+
17+
| Pojęcie PL | Nazwa w kodzie | Opis |
18+
|---|---|---|
19+
| Zlecenie produkcyjne | `WorkOrder` | Główna jednostka — co produkujemy, ile, gdzie, kiedy |
20+
| Linia produkcyjna | `Line` | Fizyczne miejsce produkcji |
21+
| Stanowisko | `Workstation` | Konkretna maszyna/miejsce pracy na linii |
22+
| Typ produktu | `ProductType` | Kategoria/rodzaj produktu |
23+
| Szablon procesu | `ProcessTemplate` | Definicja kroków technologicznych dla produktu |
24+
| Krok szablonu | `TemplateStep` | Pojedyncza operacja w szablonie (np. spawanie, malowanie) |
25+
| Partia | `Batch` | Realizacja zlecenia — rzeczywiste wykonanie produkcji |
26+
| Krok partii | `BatchStep` | Wykonanie konkretnego kroku dla danej partii |
27+
| Usterka / problem | `Issue` | Zgłoszony problem jakościowy lub awaria |
28+
| Typ usterki | `IssueType` | Kategoria problemu (awaria, braki, jakość...) |
29+
| Import CSV/XLS | `CsvImport` | Import zleceń produkcyjnych z pliku |
30+
| Mapowanie importu | `CsvImportMapping` | Zapamiętany profil mapowania kolumn pliku |
31+
| Ustawienia systemu | `system_settings` (tabela key/value) | Konfiguracja globalna (okres produkcji, reguły) |
32+
33+
---
34+
35+
## 3. Cykl życia zlecenia produkcyjnego (WorkOrder)
36+
37+
Wzorowany na Qcadoo, uproszczony:
38+
39+
```
40+
oczekujące → zaakceptowane → w toku → zakończone
41+
↘ wstrzymane → wznowione → w toku
42+
↘ odrzucone
43+
```
44+
45+
Statusy w kodzie (do ustalenia/rozbudowy):
46+
- `pending` — nowe zlecenie
47+
- `accepted` — zatwierdzone do produkcji
48+
- `in_progress` — produkcja trwa
49+
- `completed` — zakończone
50+
- `paused` — wstrzymane
51+
- `rejected` — odrzucone
52+
53+
Przy każdej zmianie statusu warto logować: kto, kiedy, z jakiego statusu, do jakiego.
54+
55+
---
56+
57+
## 4. Kluczowe encje i relacje (docelowe)
58+
59+
### WorkOrder
60+
- `order_no` — unikalny numer zlecenia (wymagany przy imporcie)
61+
- `product_name` — nazwa produktu
62+
- `quantity` — ilość do wyprodukowania (wymagana przy imporcie)
63+
- `line_id``Line` — linia produkcyjna
64+
- `product_type_id``ProductType`
65+
- `process_template_id``ProcessTemplate`
66+
- `priority` — priorytet (np. 1-5)
67+
- `due_date` — termin realizacji
68+
- `status` — aktualny status zlecenia
69+
- `week_number` — numer tygodnia produkcyjnego
70+
- `month_number` — numer miesiąca produkcyjnego
71+
- `production_year` — rok produkcji
72+
73+
### Line (Linia produkcyjna)
74+
- `name`, `code`, `description`
75+
- `is_active` — czy linia aktywna
76+
- Może mieć wiele stanowisk (`Workstation`)
77+
- Zlecenia są przypisywane do linii
78+
79+
### ProcessTemplate (Szablon procesu / Technologia)
80+
- Odpowiednik `technologies_technology` z Qcadoo
81+
- Definiuje kolejność kroków produkcyjnych dla danego produktu
82+
- Ma wiele `TemplateStep` (kroków)
83+
84+
### TemplateStep (Krok procesu)
85+
- Odpowiednik `technologies_operation` z Qcadoo
86+
- `name`, `order` (kolejność), `required_role`
87+
- Może wymagać potwierdzenia przez operatora
88+
89+
### Batch (Partia / Realizacja)
90+
- Odpowiednik `productioncounting_productiontracking` z Qcadoo
91+
- Tworzona gdy zlecenie przechodzi do `in_progress`
92+
- Przechodzi przez kroki (`BatchStep`) odpowiadające krokom szablonu
93+
94+
### BatchStep
95+
- Stan: `pending``in_progress``done` / `failed`
96+
- Kto wykonał, kiedy, ile czasu
97+
98+
### Issue (Usterka / Problem)
99+
- Powiązana z zleceniem lub krokiem partii
100+
- `issue_type_id``IssueType`
101+
- Opis, status, kto zgłosił
102+
103+
---
104+
105+
## 5. Logika importu (CSV/XLS/XLSX)
106+
107+
Import zleceń produkcyjnych z pliku zewnętrznego (np. export z ERP/Excel).
108+
109+
**Przepływ:**
110+
1. Upload pliku → `CsvImportController::upload()` → parsuje nagłówki → widok mapowania
111+
2. Mapowanie kolumn → `CsvImportController::process()` → walidacja → zapis `WorkOrder`
112+
3. Pola wymagane: `order_no` + `quantity`
113+
4. Opcjonalne: przypisanie do linii, tygodnia/miesiąca/roku produkcji
114+
115+
**Strategie importu:**
116+
- `insert_only` — tylko nowe rekordy
117+
- `update_only` — tylko aktualizacja istniejących
118+
- `insert_or_update` — upsert
119+
120+
**Ustawienia produkcji (system_settings):**
121+
- `production_period`: `none` / `weekly` / `monthly` — czy import wymaga podania numeru tygodnia lub miesiąca
122+
- `allow_overproduction`: czy można przekroczyć zaplanowaną ilość
123+
- `force_sequential_steps`: czy kroki muszą być wykonywane w kolejności
124+
125+
---
126+
127+
## 6. Wzorce z Qcadoo do zastosowania w OpenMES
128+
129+
### Śledzenie czasu operacji
130+
- TPZ — czas przygotowania/przezbrojenia stanowiska (setup time)
131+
- TJ — czas jednostkowy operacji (czas na 1 sztukę)
132+
- Czas maszyny vs. czas pracy ludzkiej (mogą się różnić)
133+
134+
### Rodzaje rejestracji produkcji
135+
- **Skumulowana** — jeden rekord dla całego zlecenia (proste zlecenia)
136+
- **Na każdą operację** — szczegółowe śledzenie każdego kroku
137+
138+
### Typy przepływu materiału
139+
- W ramach procesu (produkty nie opuszczają linii)
140+
- Między operacjami (półprodukty trafiają do magazynu między krokami)
141+
- Partiami (produkcja wsadowa — chemia, spożywka)
142+
143+
### Genealogia / Traceability (do rozbudowy w przyszłości)
144+
- Śledzenie z której partii surowca powstał produkt
145+
- `Batch` z numerem partii, dostawcą, datą
146+
- Powiązanie batch → zlecenie → gotowy produkt
147+
148+
### Anomalie
149+
- Odchylenie od planu (wyprodukowano więcej/mniej niż planowano)
150+
- Wymaga wyjaśnienia / korekty
151+
- W Qcadoo: `productioncounting_anomaly`
152+
153+
---
154+
155+
## 7. Role użytkowników
156+
157+
| Rola | Dostęp |
158+
|---|---|
159+
| `Admin` | Pełny dostęp: ustawienia, import, zarządzanie wszystkim |
160+
| `Supervisor` | Zarządzanie zleceniami, liniami, raportami |
161+
| `Operator` | Widok swoich zadań, rejestracja kroków, zgłaszanie usterek |
162+
| `Workstation` | Konto dla stanowiska (bez logowania użytkownika), ograniczony widok |
163+
164+
Implementacja: Spatie Laravel Permission (`hasRole`, `hasPermissionTo`).
165+
166+
---
167+
168+
## 8. Moduły systemu (pluginy)
169+
170+
OpenMES wspiera system modułów (`modules/` w katalogu projektu).
171+
Moduł to rozszerzenie funkcjonalności — może dodawać widoki, trasy, logikę.
172+
Moduły są włączane/wyłączane przez Admin w ustawieniach.
173+
174+
---
175+
176+
## 9. Priorytety rozwoju (kolejność implementacji)
177+
178+
1. **Stabilny import** — CSV/XLS, mapowanie, przypisanie do linii/tygodnia ✅
179+
2. **Statusy zleceń** — pełny workflow ze zmianami statusu i logiem
180+
3. **Partia i kroki** — Batch + BatchStep, rejestracja wykonania przez operatora
181+
4. **Usterki** — Issue z linkiem do zlecenia/kroku
182+
5. **Dashboard** — przegląd statusów linii, zleceń w toku, alertów
183+
6. **Raporty** — produkcja na zmianę/tydzień/miesiąc, wydajność linii
184+
7. **Czas operacji** — rejestracja czasu pracy przy kroku
185+
8. **Genealogia batch** — traceability z/do surowców
186+
187+
---
188+
189+
## 10. Konwencje techniczne projektu
190+
191+
- **Backend**: Laravel 12, PHP 8.3, PostgreSQL
192+
- **Frontend**: Blade + Alpine.js + Tailwind CSS 4 (Vite)
193+
- **Auth**: Laravel Sanctum, session-based
194+
- **Role**: Spatie Permission
195+
- **Import**: PhpOffice\PhpSpreadsheet (przez maatwebsite/excel)
196+
- **Walidacja**: Form Requests (nigdy tylko frontend)
197+
- **Baza**: Eloquent/Query Builder — zero raw SQL z userinputem
198+
- **Docker (dev/prod)**: `docker compose up -d` — tryb sterowany przez `.env` (`APP_ENV=local` lub `production`)
199+
- **Testy**: `php artisan test`
200+
- **Lint**: `./vendor/bin/pint`
201+
202+
### Język interfejsu (i18n)
203+
204+
**Domyślny język aplikacji to angielski (EN).**
205+
206+
Wszystkie teksty w kodzie — widoki Blade, kontrolery (flash messages), walidacja (Form Requests), seedery (nazwy domyślnych rekordów), etykiety formularzy, buttony, breadcrumbs, tooltips — **muszą być napisane po angielsku**.
207+
208+
Tłumaczenie na polski (i inne języki) będzie realizowane przez system tłumaczeń Laravel (`lang/`), ale **kod źródłowy zawsze zawiera angielskie stringi jako bazę**.
209+
210+
**Zasada:** English first → Polish (and other languages) via translation files.
211+
212+
---
213+
214+
## 11. Środowisko testowe (docker lokalny)
215+
216+
- **Ścieżka**: `/home/themreviil/Documents/test/omtest`
217+
- **Klon z**: `main` branch repozytorium
218+
- **Konfiguracja**: `.env` z `APP_ENV=local`, `APP_PORT=8080`
219+
- **Uruchamianie**: `docker compose up -d` w katalogu `/home/themreviil/Documents/test/omtest`
220+
- **Dostęp**: http://localhost:8080
221+
- **Aktualizacja**: `git pull && docker compose up -d --build`
222+
- **Cel**: manualne testowanie przed pushem do main
223+
224+
---
225+
226+
## 12. Wdrożenie na Apache2 (bez Dockera)
227+
228+
Alternatywna metoda instalacji — bezpośrednio na serwerze z PHP i Apache2.
229+
230+
**Wymagania:** PHP 8.3, rozszerzenia: `pdo_pgsql`, `mbstring`, `zip`, `gd`, `opcache`, Node.js (do builda assetów), Composer, PostgreSQL
231+
232+
**Kroki:**
233+
```bash
234+
# 1. Sklonuj repo
235+
git clone https://github.com/Mes-Open/OpenMes.git /var/www/openmmes
236+
cd /var/www/openmmes/backend
237+
238+
# 2. Zainstaluj zależności i zbuduj assety
239+
composer install --no-dev --optimize-autoloader
240+
npm ci && npm run build
241+
242+
# 3. Uprawnienia
243+
chown -R www-data:www-data storage bootstrap/cache
244+
chmod -R 775 storage bootstrap/cache
245+
246+
# 4. Skonfiguruj .env
247+
cp .env.example .env
248+
php artisan key:generate
249+
# → edytuj .env: DB_*, APP_URL
250+
```
251+
252+
**Virtual host Apache2** (`/etc/apache2/sites-available/openmmes.conf`):
253+
```apache
254+
<VirtualHost *:80>
255+
ServerName openmmes.local
256+
DocumentRoot /var/www/openmmes/backend/public
257+
258+
<Directory /var/www/openmmes/backend/public>
259+
AllowOverride All
260+
Require all granted
261+
</Directory>
262+
</VirtualHost>
263+
```
264+
265+
```bash
266+
a2enmod rewrite
267+
a2ensite openmmes
268+
systemctl reload apache2
269+
```
270+
271+
**Uwaga:** `public/.htaccess` jest już w repo — Laravel routing działa bez żadnych dodatkowych zmian.
272+
273+
---
274+
275+
## 13. Moduły (NIGDY na publicznym repo)
276+
277+
Katalog `modules/` jest w `.gitignore` — nic z niego nie trafia do repo.
278+
Pre-commit hook blokuje każdy commit dotyczący `modules/`.
279+
280+
Każdy moduł ma osobne repozytorium (publiczne lub prywatne).
281+
282+
| Moduł | Repo | Typ |
283+
|---|---|---|
284+
| Packaging | bundled (historia w repo) | Open source |
285+
| SubiektNexo | `Mes-Open/subiekt-nexo-module` (PRIVATE) | Komercyjny |
286+
287+
**Zasady:**
288+
- NIGDY nie commituj nic do `modules/` w tym repo
289+
- Nowy moduł = nowe repo (`Mes-Open/<nazwa>`)
290+
- Na instancji klienta: `cd modules/ \&\& git clone <repo> <NazwaModulu>`

backend/app/Http/Controllers/Web/Admin/DashboardController.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,18 @@ public function index(Request $request)
7575
->groupBy('line_id')
7676
->map(fn ($records) => $records->first());
7777

78+
$enabledWidgets = \App\Models\DashboardWidget::enabled()
79+
->pluck('widget_id')
80+
->toArray();
81+
82+
$widgetOrder = \App\Models\DashboardWidget::orderBy('sort_order')
83+
->where('enabled', true)
84+
->pluck('widget_id')
85+
->toArray();
86+
7887
return view('admin.dashboard', compact(
7988
'stats', 'recentWorkOrders', 'recentIssues',
80-
'lines', 'selectedLineId', 'oeeRecords'
89+
'lines', 'selectedLineId', 'oeeRecords', 'enabledWidgets', 'widgetOrder'
8190
));
8291
}
8392
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
namespace App\Http\Controllers\Web\Admin;
4+
5+
use App\Http\Controllers\Controller;
6+
use App\Models\DashboardWidget;
7+
use Illuminate\Http\Request;
8+
9+
class DashboardWidgetController extends Controller
10+
{
11+
public function index()
12+
{
13+
$widgets = DashboardWidget::orderBy('sort_order')->get();
14+
15+
return view('admin.dashboard-widgets.index', compact('widgets'));
16+
}
17+
18+
public function toggle(DashboardWidget $widget)
19+
{
20+
$widget->update(['enabled' => ! $widget->enabled]);
21+
22+
return back()->with('success', ($widget->enabled ? 'Enabled' : 'Disabled').': '.$widget->name);
23+
}
24+
25+
public function reorder(Request $request)
26+
{
27+
$validated = $request->validate([
28+
'order' => 'required|array',
29+
'order.*' => 'integer|exists:dashboard_widgets,id',
30+
]);
31+
32+
foreach ($validated['order'] as $position => $id) {
33+
DashboardWidget::where('id', $id)->update(['sort_order' => ($position + 1) * 10]);
34+
}
35+
36+
return response()->json(['success' => true]);
37+
}
38+
39+
public function saveAll(Request $request)
40+
{
41+
$validated = $request->validate([
42+
'widgets' => 'required|array',
43+
'widgets.*.id' => 'required|integer|exists:dashboard_widgets,id',
44+
'widgets.*.enabled' => 'required|boolean',
45+
]);
46+
47+
foreach ($validated['widgets'] as $position => $data) {
48+
DashboardWidget::where('id', $data['id'])->update([
49+
'enabled' => $data['enabled'],
50+
'sort_order' => ($position + 1) * 10,
51+
]);
52+
}
53+
54+
return response()->json(['success' => true]);
55+
}
56+
}

backend/app/Http/Controllers/Web/Operator/LineController.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ public function select(Request $request)
7272
$defaultView = $line?->default_operator_view ?? 'queue';
7373
$route = $defaultView === 'workstation' ? 'operator.workstation' : 'operator.queue';
7474

75-
return redirect()->route($route)
76-
->with('success', 'Line selected successfully.');
75+
return redirect()->route($route);
7776
}
7877
}

0 commit comments

Comments
 (0)