This commit is contained in:
2026-03-22 23:54:59 +01:00
parent 91963d5173
commit 686429d9cf
20 changed files with 721 additions and 61 deletions

View File

@@ -0,0 +1,47 @@
#!/usr/bin/env node
/**
* SessionStart hook: reminds Claude to index DOCS/*.md into context-mode.
* Scans for DOCS/ or docs/ folder and lists .md files to index.
*/
import { readdirSync, statSync, existsSync } from 'fs';
import { join, relative } from 'path';
const projectRoot = process.env.PROJECT_DIR || process.cwd();
let docsDir = null;
for (const candidate of ['DOCS', 'docs']) {
const fullPath = join(projectRoot, candidate);
if (existsSync(fullPath)) {
docsDir = fullPath;
break;
}
}
if (!docsDir) {
process.exit(0);
}
function getMdFiles(dir) {
const files = [];
for (const entry of readdirSync(dir, { withFileTypes: true })) {
const fullPath = join(dir, entry.name);
if (entry.isDirectory()) {
files.push(...getMdFiles(fullPath));
} else if (entry.name.endsWith('.md')) {
files.push(relative(projectRoot, fullPath).replace(/\\/g, '/'));
}
}
return files;
}
const mdFiles = getMdFiles(docsDir);
if (mdFiles.length > 0) {
const instructions = {
result: "INDEX_DOCS_REMINDER",
message: `Na starcie sesji zaindeksuj poniższe pliki dokumentacji do context-mode (ctx_index) aby oszczędzać okno kontekstu. Użyj pełnych ścieżek z PROJECT_DIR.`,
files: mdFiles,
projectDir: projectRoot.replace(/\\/g, '/')
};
console.log(JSON.stringify(instructions));
}

12
.claude/memory/MEMORY.md Normal file
View File

@@ -0,0 +1,12 @@
# Memory Index — orderPRO
## Feedback
- [feedback_concerns_cleanup.md](feedback_concerns_cleanup.md) — Po naprawieniu concern: usunąć go z CONCERNS.md całkowicie
- [feedback_polish_language.md](feedback_polish_language.md) — Zawsze pisz po polsku w tym projekcie
- [feedback_screenshots_dir.md](feedback_screenshots_dir.md) — Screenshoty zapisywać w .claude/screenshots/, nie w katalogu głównym
## Reference
- [reference_server_deploy.md](reference_server_deploy.md) — FTP deploy na hostido, vendor/ bez dev deps, usuwanie ręczne
- [reference_agent_login.md](reference_agent_login.md) — Dane logowania konta technicznego Claude Agent do panelu orderPRO

View File

@@ -0,0 +1,11 @@
---
name: feedback_concerns_cleanup
description: Po naprawieniu buga/concern — usuwać wpis z CONCERNS.md (nie zostawiać przekreślonego ani niezmienionego)
type: feedback
---
Po naprawieniu każdego wpisu z `.paul/codebase/CONCERNS.md`**usuń go całkowicie** z pliku.
**Why:** Zostawienie naprawionego concern (nawet przekreślonego ~~jak to~~) powoduje dezorientację — user wraca do starych wpisów myśląc, że bug jest aktywny (jak "Application.php Manually Instantiates Full Object Graph" który był już fixed w Plan 02-04).
**How to apply:** Po każdym UNIFY — sprawdź czy któryś concern z CONCERNS.md został rozwiązany w tym planie. Jeśli tak, usuń go całkowicie. Wyjątek: wpis z notatką o zmianie (jak AllegroStatusSyncService ~~przekreślony~~ z adnotacją) — można zostawić tymczasowo, ale i tak lepiej usunąć.

View File

@@ -0,0 +1,11 @@
---
name: Pisz po polsku
description: Użytkownik chce, żeby Claude zawsze komunikował się po polsku w tym projekcie
type: feedback
---
Zawsze pisz po polsku — odpowiedzi, komentarze, statusy, pytania.
**Why:** Użytkownik wyraźnie poprosił o komunikację po polsku.
**How to apply:** Każda odpowiedź tekstowa ma być po polsku. Kod, nazwy klas/metod i komentarze techniczne w kodzie pozostają po angielsku (konwencja projektu).

View File

@@ -0,0 +1,13 @@
---
name: screenshots_dir
description: Screenshoty w .claude/screenshots/ projektu, przeglądarka 1920px szerokości
type: feedback
---
Screenshoty z Puppeteer zapisuj w `.claude/screenshots/` **w katalogu projektu** (np. `C:\visual studio code\projekty\orderPRO\.claude\screenshots\<nazwa>.png`).
Przy uruchamianiu przeglądarki Puppeteer ustawiaj viewport na szerokość **1920px**.
**Why:** Katalog `/.claude` jest na liście ignore ftp-kr, więc pliki tam nie są wysyłane na serwer. Użytkownik pracuje na monitorze 1920px i chce widzieć realny układ.
**How to apply:** Przy każdym `puppeteer_launch` ustawiaj `viewport.width: 1920`. Przy każdym `puppeteer_screenshot` używaj ścieżki w `C:\visual studio code\projekty\orderPRO\.claude\screenshots\`.

View File

@@ -0,0 +1,11 @@
---
name: sonarqube_setup_pending
description: Użytkownik chce skonfigurować SonarQube na serwerze Hetzner (Windows + Docker) - potrzebuje pomocy krok po kroku
type: project
---
Użytkownik chce skonfigurować SonarQube krok po kroku na dedykowanym serwerze Hetzner z Windows i Dockerem.
**Why:** Integracja z Claude Code przez MCP dla analizy jakości kodu projektu orderPRO.
**How to apply:** Przy pierwszej okazji po zakończeniu bieżącego zadania przypomnij o konfiguracji SonarQube i zaproponuj przewodnik krok po kroku (Docker Compose + reverse proxy + MCP config).

View File

@@ -0,0 +1,11 @@
---
name: agent_login
description: Dane logowania konta technicznego Claude Agent do panelu orderPRO
type: reference
---
Konto techniczne do logowania na stronie orderPRO:
- URL: https://orderpro.projectpro.pl/login
- Email: agent@orderpro.local
- Haslo: ClaudeAgent2026!
- User ID w bazie: 2

View File

@@ -0,0 +1,20 @@
---
name: Deployment na serwer produkcyjny
description: FTP deploy na hostido — vendor/ musi być bez dev deps, upload automatyczny ale usuwanie ręczne
type: reference
---
Serwer: host700513.hostido.net.pl (FTP, port 21)
Dane w: .vscode/sftp.json
Remote path: /public_html
Upload plików na serwer odbywa się automatycznie (VS Code SFTP plugin).
Usuwanie plików z serwera NIE jest automatyczne — trzeba ręcznie.
**vendor/ na serwerze:**
- Użytkownik NIE ma composera na serwerze
- vendor/ musi być zbudowany lokalnie z `--no-dev` przed wrzuceniem na serwer
- Komenda: `php composer.phar install --no-dev --optimize-autoloader --ignore-platform-reqs`
- Nie wrzucaj dev dependencies (phpunit, bypass-finals) na serwer — powoduje fatal error
**How to apply:** Przy każdej zmianie composer.json/vendor/ — pamiętaj o deploy vendor/ bez dev deps.

View File

@@ -22,7 +22,24 @@
"Bash(php tmp_gs1_test.php)",
"mcp__serena__write_memory",
"mcp__serena__prepare_for_new_conversation",
"Bash(npx sass:*)"
"Bash(npx sass:*)",
"Bash(PROJECT_DIR=\"C:/visual studio code/projekty/orderPRO\" node .claude/hooks/index-docs.mjs)",
"mcp__plugin_context-mode_context-mode__ctx_index",
"mcp__plugin_context-mode_context-mode__ctx_search",
"mcp__plugin_context-mode_context-mode__ctx_batch_execute"
]
},
"hooks": {
"SessionStart": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "node .claude/hooks/index-docs.mjs"
}
]
}
]
}
}

4
.env
View File

@@ -13,4 +13,6 @@ DB_USERNAME=host700513_orderpro
DB_PASSWORD=hrDNtUBg9grwZ7syN77S
DB_CHARSET=utf8mb4
INTEGRATIONS_SECRET=nB3sTkXAbBLqA2Ent74R9Mi1118bAbWa
INTEGRATIONS_SECRET=nB3sTkXAbBLqA2Ent74R9Mi1118bAbWa
pracownia.key=9554daf4bbcbbb5e72a2b48ee7d6a7f20262713d72484b781460e2c772d813fc

View File

@@ -216,7 +216,7 @@ PLAN ──▶ APPLY ──▶ UNIFY
- **Delivery mapping "Szukaj..." layout** — JS `attachSelectFilter()` w allegro.php tworzy input search dla InPost/Apaczka selectów, wizualnie wygląda jakby należał do wiersza powyżej. Pre-existing bug, do naprawy osobno.
### Git State
Last commit: e379557 — feat(24-shipment-presets-ui): kolorowe przyciski presetów, popup, autofill
Last commit: 91963d5 — feat(25-shipment-presets-management): edycja, usuwanie, zarządzanie presetami
Branch: main
Feature branches merged: none

View File

@@ -0,0 +1,162 @@
---
phase: 21-order-source-display
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- src/Modules/Orders/OrdersRepository.php
- src/Modules/Orders/OrdersController.php
- resources/views/orders/show.php
autonomous: true
---
<objective>
## Goal
Poprawic wyswietlanie zrodla zamowienia na liscie zamowien i stronie szczegulow:
1. (todo #15) Upewnic sie, ze w `orders-ref__meta` kolejnosc to: zrodlo, potem ID (weryfikacja — kod juz moze byc poprawny)
2. (todo #17) Zamiast generycznego "shopPRO" wyswietlac nazwe konkretnej integracji z tabeli `integrations` (np. "Moj Sklep 1"). Dotyczy listy zamowien i strony szczegulow. Dodac prefiks "ID:" przed identyfikatorem zamowienia.
## Purpose
Sprzedawca z wieloma sklepami shopPRO musi wiedziec, z ktorego konkretnie sklepu pochodzi zamowienie.
## Output
Zmodyfikowane pliki: OrdersRepository.php, OrdersController.php, show.php
</objective>
<context>
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
@.paul/STATE.md
## Source Files
@src/Modules/Orders/OrdersRepository.php
@src/Modules/Orders/OrdersController.php
@resources/views/orders/show.php
@DOCS/todo.md
</context>
<skills>
No specialized flows required for this plan.
</skills>
<acceptance_criteria>
## AC-1: Integration name displayed on orders list
```gherkin
Given zamowienie pochodzi z integracji shopPRO o nazwie "Moj Sklep"
When uzytkownik otwiera liste zamowien
Then w kolumnie "Numer" w sekcji orders-ref__meta widzi "Moj Sklep" zamiast "shopPRO"
And widzi "ID: <source_order_id>" jako drugi element
```
## AC-2: Integration name displayed on order detail page
```gherkin
Given zamowienie pochodzi z integracji shopPRO o nazwie "Moj Sklep"
When uzytkownik otwiera szczegoly zamowienia
Then w naglowku pod numerem zamowienia widzi "Moj Sklep" i identyfikator zamowienia
```
## AC-3: Allegro/Erli orders unaffected
```gherkin
Given zamowienie pochodzi z Allegro
When uzytkownik otwiera liste zamowien
Then w sekcji orders-ref__meta widzi "Allegro" jako zrodlo (bez zmian)
And widzi "ID: <source_order_id>" jako identyfikator
```
## AC-4: Source first, ID second in meta
```gherkin
Given dowolne zamowienie na liscie
When uzytkownik patrzy na kolumne "Numer"
Then pierwszy span w orders-ref__meta to nazwa zrodla/integracji
And drugi span to "ID: <identyfikator>"
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: Dodac integration name do query listy i szczegulow</name>
<files>src/Modules/Orders/OrdersRepository.php</files>
<action>
1. W `buildListSql()`: dodac LEFT JOIN do tabeli `integrations`:
```
LEFT JOIN integrations ig ON ig.id = o.integration_id
```
Dodac kolumne `ig.name AS integration_name` do SELECT.
2. W `transformOrderRow()`: dodac pole `'integration_name' => (string) ($row['integration_name'] ?? '')` do zwracanej tablicy.
3. W `findDetails()`: dodac LEFT JOIN do `integrations` i dodac `ig.name AS integration_name` do SELECT query.
Avoid: Nie zmieniac countSql (nie potrzebuje JOIN do integrations). Nie zmieniac istniejacych kolumn — tylko dodac nowe.
</action>
<verify>Sprawdzic ze query nie rzuca bledu — otworzyc liste zamowien w przegladarce.</verify>
<done>AC-1, AC-2 — dane integration_name dostepne w wynikach query</done>
</task>
<task type="auto">
<name>Task 2: Wyswietlic integration name w UI (lista + show)</name>
<files>src/Modules/Orders/OrdersController.php, resources/views/orders/show.php</files>
<action>
1. W `OrdersController::toTableRow()`:
- Odczytac `$integrationName = trim((string) ($row['integration_name'] ?? ''));`
- Zmienic logike wyswietlania zrodla w `orders-ref__meta`:
- Jesli `$integrationName !== ''` → uzyc `$integrationName` jako label
- W przeciwnym razie → uzyc `$this->sourceLabel($source)` (fallback dla Allegro/Erli/starych danych)
- Upewnic sie ze kolejnosc spanow to: [1] zrodlo/integracja, [2] ID: identyfikator
- Obecny kod JUZ ma poprawna kolejnosc (source first), wiec tylko dodac logike integration_name
2. W `resources/views/orders/show.php` linia 48:
- Zmienic wyswietlanie z `ucfirst(source) external_order_id` na:
- Uzyc `$orderRow['integration_name']` jesli niepuste, inaczej `ucfirst(source)`
- Dodac prefiks "ID:" przed identyfikatorem
- Rozdzielic na dwa oddzielne spany (jak na liscie) dla spojnosci
3. Metoda `sourceLabel()` — pozostawic bez zmian (fallback).
Avoid: Nie zmieniac CSS. Nie zmieniac filtrow zrodla (dropdown). Nie zmieniac logiki statusow.
</action>
<verify>Otworzyc liste zamowien — zamowienia shopPRO pokazuja nazwe integracji. Allegro pokazuje "Allegro". Otworzyc szczegoly zamowienia — naglowek pokazuje nazwe integracji.</verify>
<done>AC-1, AC-2, AC-3, AC-4 satisfied</done>
</task>
</tasks>
<boundaries>
## DO NOT CHANGE
- resources/scss/* (zadnych zmian CSS)
- Filtry zrodla w dropdownie (sourceOptions) — poza zakresem
- Logika statusow, platnosci, przesylek
- Inne widoki niz show.php
## SCOPE LIMITS
- Tylko wyswietlanie — bez zmian w logice importu zamowien
- Bez zmian w bazie danych (kolumna integration_id juz istnieje w orders)
- Bez nowych zaleznosci
</boundaries>
<verification>
Before declaring plan complete:
- [ ] Lista zamowien laduje sie bez bledow
- [ ] Zamowienia shopPRO pokazuja nazwe integracji (nie "shopPRO")
- [ ] Zamowienia Allegro pokazuja "Allegro" (bez regresji)
- [ ] Strona szczegulow zamowienia pokazuje nazwe integracji
- [ ] Kolejnosc w orders-ref__meta: zrodlo first, ID second
- [ ] All acceptance criteria met
</verification>
<success_criteria>
- Todo #15 i #17 zrealizowane
- Brak regresji na liscie zamowien i stronie szczegulow
- Kod uzywa prepared statements (medoo/PDO) — brak SQL injection
</success_criteria>
<output>
After completion, create `.paul/phases/21-order-source-display/21-01-SUMMARY.md`
</output>

View File

@@ -0,0 +1,100 @@
---
phase: 21-order-source-display
plan: 01
subsystem: ui
tags: [orders, integrations, display]
requires:
- phase: none
provides: n/a
provides:
- integration name display on orders list
- integration name display on order detail page
affects: []
tech-stack:
added: []
patterns: [integration name fallback pattern]
key-files:
created: []
modified:
- src/Modules/Orders/OrdersRepository.php
- src/Modules/Orders/OrdersController.php
- resources/views/orders/show.php
key-decisions:
- "Fallback: integration_name → sourceLabel() dla Allegro/Erli/starych danych"
patterns-established:
- "Integration name resolution: prefer integrations.name, fallback to sourceLabel(source)"
duration: 5min
started: 2026-03-22T00:00:00Z
completed: 2026-03-22T00:00:00Z
---
# Phase 21 Plan 01: Order Source Display Summary
**LEFT JOIN integrations w query zamowien — lista i szczegoly pokazuja nazwe integracji zamiast generycznego "shopPRO"**
## Performance
| Metric | Value |
|--------|-------|
| Duration | ~5min |
| Tasks | 2 completed |
| Files modified | 3 |
## Acceptance Criteria Results
| Criterion | Status | Notes |
|-----------|--------|-------|
| AC-1: Integration name on list | Pass | LEFT JOIN integrations, fallback na sourceLabel |
| AC-2: Integration name on detail | Pass | show.php uzywa integration_name z order row |
| AC-3: Allegro/Erli unaffected | Pass | Fallback na sourceLabel() gdy integration_name puste |
| AC-4: Source first, ID second | Pass | Kod listy juz mial poprawna kolejnosc; show.php poprawiony |
## Accomplishments
- Query listy zamowien i szczegulow dolacza tabele `integrations` (LEFT JOIN) i zwraca `integration_name`
- Lista zamowien wyswietla nazwe integracji (np. "Moj Sklep") zamiast generycznego "shopPRO"
- Strona szczegulow zamowienia rozdzielona na dwa spany z prefiksem "ID:"
## Files Created/Modified
| File | Change | Purpose |
|------|--------|---------|
| `src/Modules/Orders/OrdersRepository.php` | Modified | LEFT JOIN integrations w buildListSql + findDetails; integration_name w transformOrderRow |
| `src/Modules/Orders/OrdersController.php` | Modified | toTableRow uzywa integration_name z fallbackiem na sourceLabel |
| `resources/views/orders/show.php` | Modified | Naglowek: osobne spany, nazwa integracji + prefiks "ID:" |
## Decisions Made
| Decision | Rationale | Impact |
|----------|-----------|--------|
| Fallback na sourceLabel() gdy integration_name puste | Allegro/Erli nie maja wpisow w integrations dla kazdego zamowienia; stare zamowienia moga miec NULL integration_id | Brak regresji |
## Deviations from Plan
None — plan executed exactly as written.
## Issues Encountered
None.
## Next Phase Readiness
**Ready:**
- Todo #15 i #17 zrealizowane
- Milestone v0.8 gotowy do zamkniecia
**Concerns:**
- None
**Blockers:**
- None
---
*Phase: 21-order-source-display, Plan: 01*
*Completed: 2026-03-22*

View File

@@ -2,5 +2,5 @@ projectKey=orderPRO
serverUrl=https://sonar.project-pro.pl
serverVersion=26.3.0.120487
dashboardUrl=https://sonar.project-pro.pl/dashboard?id=orderPRO
ceTaskId=32235c87-2f61-4232-9bc1-37cdc4234595
ceTaskUrl=https://sonar.project-pro.pl/api/ce/task?id=32235c87-2f61-4232-9bc1-37cdc4234595
ceTaskId=16807b34-3042-4ded-9751-89e00701d085
ceTaskUrl=https://sonar.project-pro.pl/api/ce/task?id=16807b34-3042-4ded-9751-89e00701d085

View File

@@ -474,9 +474,9 @@
},
"composer.json": {
"type": "-",
"size": 687,
"lmtime": 1772489482442,
"modified": true
"size": 722,
"lmtime": 1773786224662,
"modified": false
},
"composer.lock": {
"type": "-",
@@ -874,8 +874,14 @@
},
"20260316_000001_add_attachment1_to_email_templates.sql": {
"type": "-",
"size": 96,
"lmtime": 1773701415069,
"size": 378,
"lmtime": 1773787052845,
"modified": false
},
"20260318_000057_create_automation_tables.sql": {
"type": "-",
"size": 1631,
"lmtime": 1773789478088,
"modified": false
}
},
@@ -928,14 +934,14 @@
"DOCS": {
"ARCHITECTURE.md": {
"type": "-",
"size": 31763,
"lmtime": 1773615416923,
"size": 32951,
"lmtime": 1773790245031,
"modified": false
},
"DB_SCHEMA.md": {
"type": "-",
"size": 27900,
"lmtime": 1773701554836,
"size": 29737,
"lmtime": 1773789666999,
"modified": false
},
"ORDERS_SCHEMA_APILO_DRAFT.md": {
@@ -952,15 +958,15 @@
},
"TECH_CHANGELOG.md": {
"type": "-",
"size": 46908,
"lmtime": 1773615432190,
"size": 49699,
"lmtime": 1773790252961,
"modified": false
},
"todo.md": {
"type": "-",
"size": 2051,
"lmtime": 1772997209432,
"modified": true
"size": 2129,
"lmtime": 1773790444877,
"modified": false
}
},
".env": {
@@ -2189,8 +2195,8 @@
"css": {
"app.css": {
"type": "-",
"size": 36918,
"lmtime": 1773616475105,
"size": 48246,
"lmtime": 1773789643914,
"modified": false
},
"app.css.map": {
@@ -2228,6 +2234,12 @@
"size": 5768,
"lmtime": 1771873304132,
"modified": false
},
"automation-form.js": {
"type": "-",
"size": 5053,
"lmtime": 1773789606719,
"modified": false
}
}
}
@@ -2250,8 +2262,8 @@
"lang": {
"pl.php": {
"type": "-",
"size": 56930,
"lmtime": 1773009492281,
"size": 62881,
"lmtime": 1773788074010,
"modified": false
}
},
@@ -2286,8 +2298,8 @@
},
"app.scss": {
"type": "-",
"size": 42386,
"lmtime": 1773616457946,
"size": 42442,
"lmtime": 1773789619255,
"modified": false
},
"login.css": {
@@ -2308,6 +2320,20 @@
"lmtime": 1771866989000,
"modified": false
},
"modules": {
"_email-send.scss": {
"type": "-",
"size": 2093,
"lmtime": 1773786622096,
"modified": false
},
"_automation.scss": {
"type": "-",
"size": 1038,
"lmtime": 1773789611848,
"modified": false
}
},
"shared": {
"_ui-components.scss": {
"type": "-",
@@ -2318,6 +2344,7 @@
}
},
"views": {
"accounting": {},
"auth": {
"login.php": {
"type": "-",
@@ -2351,8 +2378,8 @@
"layouts": {
"app.php": {
"type": "-",
"size": 8934,
"lmtime": 1773616408513,
"size": 9146,
"lmtime": 1773789621995,
"modified": false
},
"auth.php": {
@@ -2389,10 +2416,24 @@
"lmtime": 1773004094862,
"modified": false
},
"partials": {
"email-send-modal.php": {
"type": "-",
"size": 7455,
"lmtime": 1773786546755,
"modified": false
}
},
"receipt-create.php": {
"type": "-",
"size": 4987,
"lmtime": 0,
"modified": false
},
"show.php": {
"type": "-",
"size": 27463,
"lmtime": 1773359729566,
"size": 31864,
"lmtime": 1773787790160,
"modified": false
}
},
@@ -2428,6 +2469,7 @@
"modified": false
}
},
"receipts": {},
"settings": {
"accounting.php": {
"type": "-",
@@ -2520,6 +2562,14 @@
"modified": false
}
},
"shipments": {
"prepare.php": {
"type": "-",
"size": 32252,
"lmtime": 1773359733203,
"modified": false
}
},
"users": {
"index.php": {
"type": "-",
@@ -2528,11 +2578,17 @@
"modified": false
}
},
"shipments": {
"prepare.php": {
"automation": {
"index.php": {
"type": "-",
"size": 32252,
"lmtime": 1773359733203,
"size": 3962,
"lmtime": 1773789562003,
"modified": false
},
"form.php": {
"type": "-",
"size": 7536,
"lmtime": 1773789588610,
"modified": false
}
}
@@ -2541,8 +2597,8 @@
"routes": {
"web.php": {
"type": "-",
"size": 18920,
"lmtime": 1773616330514,
"size": 21001,
"lmtime": 1773790233968,
"modified": false
}
},
@@ -2741,6 +2797,26 @@
}
},
"Modules": {
"Accounting": {
"AccountingController.php": {
"type": "-",
"size": 10212,
"lmtime": 0,
"modified": false
},
"ReceiptController.php": {
"type": "-",
"size": 14363,
"lmtime": 1773790208003,
"modified": false
},
"ReceiptRepository.php": {
"type": "-",
"size": 10253,
"lmtime": 0,
"modified": false
}
},
"Auth": {
"AuthController.php": {
"type": "-",
@@ -2859,6 +2935,26 @@
"modified": false
}
},
"Email": {
"AttachmentGenerator.php": {
"type": "-",
"size": 3204,
"lmtime": 1773786316666,
"modified": false
},
"EmailSendingService.php": {
"type": "-",
"size": 12532,
"lmtime": 1773790149417,
"modified": false
},
"VariableResolver.php": {
"type": "-",
"size": 3023,
"lmtime": 1773786302912,
"modified": false
}
},
"GS1": {
"GS1Service.php": {
"type": "-",
@@ -2902,14 +2998,14 @@
},
"OrdersController.php": {
"type": "-",
"size": 27184,
"lmtime": 1773392942464,
"size": 32146,
"lmtime": 1773788099402,
"modified": false
},
"OrdersRepository.php": {
"type": "-",
"size": 31275,
"lmtime": 1773401508499,
"size": 31950,
"lmtime": 1773787170333,
"modified": false
},
"OrderStatusSyncService.php": {
@@ -3291,20 +3387,6 @@
"modified": false
}
},
"Users": {
"UserRepository.php": {
"type": "-",
"size": 5346,
"lmtime": 1771691981226,
"modified": true
},
"UsersController.php": {
"type": "-",
"size": 5179,
"lmtime": 1772491357326,
"modified": false
}
},
"Shipments": {
"AllegroShipmentService.php": {
"type": "-",
@@ -3342,6 +3424,40 @@
"lmtime": 1772999586844,
"modified": false
}
},
"Users": {
"UserRepository.php": {
"type": "-",
"size": 5346,
"lmtime": 1771691981226,
"modified": true
},
"UsersController.php": {
"type": "-",
"size": 5179,
"lmtime": 1772491357326,
"modified": false
}
},
"Automation": {
"AutomationController.php": {
"type": "-",
"size": 11363,
"lmtime": 1773789536055,
"modified": false
},
"AutomationRepository.php": {
"type": "-",
"size": 8913,
"lmtime": 1773789501115,
"modified": false
},
"AutomationService.php": {
"type": "-",
"size": 5382,
"lmtime": 1773790173434,
"modified": false
}
}
}
},
@@ -5428,7 +5544,110 @@
"modified": false
}
},
"vendor": {}
"vendor": {
"autoload.php": {
"type": "-",
"size": 748,
"lmtime": 0,
"modified": false
},
"bin": {},
"composer": {
"2723ec57": {},
"autoload_classmap.php": {
"type": "-",
"size": 181999,
"lmtime": 0,
"modified": false
},
"autoload_files.php": {
"type": "-",
"size": 8667,
"lmtime": 0,
"modified": false
},
"autoload_namespaces.php": {
"type": "-",
"size": 139,
"lmtime": 0,
"modified": false
},
"autoload_psr4.php": {
"type": "-",
"size": 1264,
"lmtime": 1773786223380,
"modified": false
},
"autoload_real.php": {
"type": "-",
"size": 1622,
"lmtime": 0,
"modified": false
},
"autoload_static.php": {
"type": "-",
"size": 206600,
"lmtime": 1773786223514,
"modified": false
},
"ClassLoader.php": {
"type": "-",
"size": 16378,
"lmtime": 0,
"modified": false
},
"installed.json": {
"type": "-",
"size": 110832,
"lmtime": 1773786222000,
"modified": false
},
"installed.php": {
"type": "-",
"size": 16083,
"lmtime": 1773786222002,
"modified": false
},
"InstalledVersions.php": {
"type": "-",
"size": 17395,
"lmtime": 0,
"modified": false
},
"LICENSE": {
"type": "-",
"size": 1070,
"lmtime": 0,
"modified": false
},
"pcre": {},
"tmp-135de45491cf02a6927c90567690c94e.zip~": {
"type": "-",
"size": 0,
"lmtime": 1773786221394,
"modified": false
}
},
"dg": {},
"dompdf": {},
"maennchen": {},
"markbaker": {},
"masterminds": {},
"myclabs": {},
"nikic": {},
"phar-io": {},
"phpoffice": {},
"phpunit": {},
"psr": {},
"sabberworm": {},
"sebastian": {},
"staabm": {},
"thecodingmachine": {},
"theseer": {},
"phpmailer": {
"phpmailer": {}
}
}
}
},
"$version": 1

View File

@@ -1,5 +1,12 @@
# Tech Changelog
## 2026-03-22 (Phase 21 — Order Source Display, Plan 01)
- `OrdersRepository::buildListSql()` — LEFT JOIN `integrations ig ON ig.id = o.integration_id`, nowa kolumna `ig.name AS integration_name`.
- `OrdersRepository::findDetails()` — analogiczny LEFT JOIN dla strony szczegolow zamowienia.
- `OrdersRepository::transformOrderRow()` — nowe pole `integration_name`.
- `OrdersController::toTableRow()` — wyswietla `integration_name` gdy niepuste, fallback na `sourceLabel()` (Allegro/Erli/default).
- `resources/views/orders/show.php` — naglowek zamowienia: dwa osobne spany (nazwa integracji + "ID: identyfikator") zamiast jednego.
## 2026-03-18 (Phase 16 — Zadania automatyczne, Plan 02: Watcher/Executor)
- Nowa klasa `App\Modules\Automation\AutomationService` — trigger + ewaluacja warunkow (AND) + wykonanie akcji.
- Flow: `ReceiptController::store()` -> `AutomationService::trigger('receipt.created', orderId)` -> sprawdzenie warunkow (integration_id) -> `EmailSendingService::send()`.

View File

@@ -1,5 +1,5 @@
15. [] W tym miejscu odwróć kolejność: najpierw źródło potem ID, <div class="orders-ref__meta"><span>f6079660-1af8-11f1-a7c9-231cf6ef29d1</span><span>allegro</span></div>
17. [] Na liście zamówien jak jest źródło i id zamówienia to zamiast shopPRO musi pisać która integracja konkretnie. Oraz dodajemy napis ID: ...D
15. [x] W tym miejscu odwróć kolejność: najpierw źródło potem ID, <div class="orders-ref__meta"><span>f6079660-1af8-11f1-a7c9-231cf6ef29d1</span><span>allegro</span></div>
17. [x] Na liście zamówien jak jest źródło i id zamówienia to zamiast shopPRO musi pisać która integracja konkretnie. Oraz dodajemy napis ID: ...D
## SonarQube — post plany 02-02 i 02-03 (skan 2026-03-13)
30. [] [Sonar 2026-03-13] Brak nowych issues — AllegroStatusSyncService i ShopproOrderSyncStateRepository czyste. Pre-existing issues w ShopproOrdersSyncService (god class) i Application.php niezmienione przez nasze modyfikacje.
@@ -28,4 +28,8 @@
33. [] [Sonar 2026-03-22] php:S2003 — show.php:696 Replace `require` with `require_once` (1x)
34. [] [Sonar 2026-03-22] php:S1448 — OrdersController ma 22 metody (limit 20) — rozdzielić (1x)
35. [] [Sonar 2026-03-22] php:S1142 — OrdersController::bulkPrint() ma 5 returnów (limit 3) (1x)
36. [] [Sonar 2026-03-22] php:S1068 — AllegroIntegrationController nieużywane pole $statusDiscoveryService (1x, pre-existing)
36. [] [Sonar 2026-03-22] php:S1068 — AllegroIntegrationController nieużywane pole $statusDiscoveryService (1x, pre-existing)
37. [x] Nie działa zapisywanie numer REGON
38. [x] Customowe przyciski paczek
39. [] Zamian głównego koloru przycisków z niebieskiego na inny (bo się z nagłówkami myli)

View File

@@ -45,7 +45,14 @@ foreach ($addressesList as $address) {
<a href="/orders/list" class="order-back-link">&larr; <?= $e($t('navigation.orders_list')) ?></a>
<h2 class="section-title mt-12"><?= $e($t('orders.details.title')) ?> <?= $e((string) ($orderRow['internal_order_number'] ?? ('#' . ($orderId ?? 0)))) ?></h2>
<div class="order-details-sub mt-12">
<span><?= $e(ucfirst((string) ($orderRow['source'] ?? ''))) ?> <?= $e((string) ($orderRow['external_order_id'] ?? '')) ?></span>
<?php
$sourceLabel = trim((string) ($orderRow['integration_name'] ?? ''));
if ($sourceLabel === '') {
$sourceLabel = ucfirst((string) ($orderRow['source'] ?? ''));
}
?>
<span><?= $e($sourceLabel) ?></span>
<span>ID: <?= $e((string) ($orderRow['external_order_id'] ?? '')) ?></span>
</div>
</div>
<div class="order-details-actions">

View File

@@ -288,6 +288,7 @@ final class OrdersController
$sourceOrderId = trim((string) ($row['source_order_id'] ?? ''));
$externalOrderId = trim((string) ($row['external_order_id'] ?? ''));
$source = trim((string) ($row['source'] ?? ''));
$integrationName = trim((string) ($row['integration_name'] ?? ''));
$buyerName = trim((string) ($row['buyer_name'] ?? ''));
$buyerEmail = trim((string) ($row['buyer_email'] ?? ''));
$buyerCity = trim((string) ($row['buyer_city'] ?? ''));
@@ -312,7 +313,7 @@ final class OrdersController
. htmlspecialchars($internalOrderNumber !== '' ? $internalOrderNumber : ('#' . (string) ($row['id'] ?? 0)), ENT_QUOTES, 'UTF-8')
. '</a></div>'
. '<div class="orders-ref__meta">'
. '<span>' . htmlspecialchars($this->sourceLabel($source), ENT_QUOTES, 'UTF-8') . '</span>'
. '<span>' . htmlspecialchars($integrationName !== '' ? $integrationName : $this->sourceLabel($source), ENT_QUOTES, 'UTF-8') . '</span>'
. '<span>ID: ' . htmlspecialchars($sourceOrderId !== '' ? $sourceOrderId : $externalOrderId, ENT_QUOTES, 'UTF-8') . '</span>'
. '</div>'
. '</div>',

View File

@@ -166,10 +166,12 @@ final class OrdersRepository
COALESCE(oi_agg.items_count, 0) AS items_count,
COALESCE(oi_agg.items_qty, 0) AS items_qty,
COALESCE(sh_agg.shipments_count, 0) AS shipments_count,
COALESCE(od_agg.documents_count, 0) AS documents_count
COALESCE(od_agg.documents_count, 0) AS documents_count,
ig.name AS integration_name
FROM orders o
LEFT JOIN order_addresses a ON a.order_id = o.id AND a.address_type = "customer"
LEFT JOIN allegro_order_status_mappings asm ON o.source = "allegro" AND LOWER(o.external_status_id) = asm.allegro_status_code
LEFT JOIN integrations ig ON ig.id = o.integration_id
LEFT JOIN (
SELECT order_id, COUNT(*) AS items_count, COALESCE(SUM(quantity), 0) AS items_qty
FROM order_items GROUP BY order_id
@@ -223,6 +225,7 @@ final class OrdersRepository
'items_qty' => (float) ($row['items_qty'] ?? 0),
'shipments_count' => (int) ($row['shipments_count'] ?? 0),
'documents_count' => (int) ($row['documents_count'] ?? 0),
'integration_name' => (string) ($row['integration_name'] ?? ''),
'items_preview' => (array) ($itemPreviewsByOrderId[$orderId] ?? []),
];
}
@@ -426,9 +429,11 @@ final class OrdersRepository
try {
$effectiveStatusSql = $this->effectiveStatusSql('o', 'asm');
$orderStmt = $this->pdo->prepare(
'SELECT o.*, ' . $effectiveStatusSql . ' AS effective_status_id
'SELECT o.*, ' . $effectiveStatusSql . ' AS effective_status_id,
ig.name AS integration_name
FROM orders o
LEFT JOIN allegro_order_status_mappings asm ON o.source = "allegro" AND LOWER(o.external_status_id) = asm.allegro_status_code
LEFT JOIN integrations ig ON ig.id = o.integration_id
WHERE o.id = :id
LIMIT 1'
);