fix(144): count imported order notes in list badge

Phase 144 complete:
- Count all order_notes rows in the /orders/list notes badge
- Add regression coverage for imported plus operator notes
- Document the combined notes badge contract

Co-Authored-By: Codex <noreply@openai.com>
This commit is contained in:
2026-05-18 12:41:32 +02:00
parent d23dec8704
commit ea039c6e8c
12 changed files with 610 additions and 30 deletions

View File

@@ -13,8 +13,8 @@ Sprzedawca moĹĽe obsĹugiwać zamĂłwienia ze wszystkich kanaĹĂłw
| Attribute | Value | | Attribute | Value |
|-----------|-------| |-----------|-------|
| Version | 3.9.0-dev | | Version | 3.9.0-dev |
| Status | v3.12 Orders List Sidebar UI Hotfix complete - Phase 143 closed | | Status | v3.13 Imported Notes Badge Count Hotfix complete - Phase 144 closed |
| Last Updated | 2026-05-18 (Phase 143 unified) | | Last Updated | 2026-05-18 (Phase 144 unified) |
## Requirements ## Requirements
@@ -143,9 +143,10 @@ Sprzedawca moĹĽe obsĹugiwać zamĂłwienia ze wszystkich kanaĹĂłw
- [x] Integrations Hub Grouped Sections: `/settings/integrations` pokazuje lekkie sekcje dla marketplace, kurierow i pozostalych integracji, bez starego naglowka/opisu wspolnego panelu — Phase 141 - [x] Integrations Hub Grouped Sections: `/settings/integrations` pokazuje lekkie sekcje dla marketplace, kurierow i pozostalych integracji, bez starego naglowka/opisu wspolnego panelu — Phase 141
- [x] Polkurier Shipment Prepare Prefill: `/orders/{id}/shipment/prepare` rozpoznaje mapowania shopPRO z `provider='polkurier'`, preselectuje przewoznika i usluge oraz nie fallbackuje do Allegro — Phase 142 - [x] Polkurier Shipment Prepare Prefill: `/orders/{id}/shipment/prepare` rozpoznaje mapowania shopPRO z `provider='polkurier'`, preselectuje przewoznika i usluge oraz nie fallbackuje do Allegro — Phase 142
- [x] Orders List Sidebar UI Hotfix: `/orders/list` startuje bez opisowego boksu "Zamowienia", a zapisany zwiniety sidebar jest stosowany przed pierwszym renderem strony — Phase 143 - [x] Orders List Sidebar UI Hotfix: `/orders/list` startuje bez opisowego boksu "Zamowienia", a zapisany zwiniety sidebar jest stosowany przed pierwszym renderem strony — Phase 143
- [x] Imported Notes Badge Count Hotfix: badge `[N]` na `/orders/list` zlicza wszystkie `order_notes` zamowienia, lacznie z notatkami importowanymi z shopPRO i notatkami autorskimi operatora — Phase 144
- [x] Integracja polkurier.pl (fundament): pojedyncza globalna konfiguracja w `/settings/integrations/polkurier`, szyfrowany Token API + login, karta w hubie integracji obok Apaczki i realny test polaczenia przez `apimetod=test_auth_api` zweryfikowany na zywym koncie operatora; `ShipmentProviderRegistry` netkniety — `PolkurierShipmentService/TrackingService` w kolejnych fazach — Phase 127 - [x] Integracja polkurier.pl (fundament): pojedyncza globalna konfiguracja w `/settings/integrations/polkurier`, szyfrowany Token API + login, karta w hubie integracji obok Apaczki i realny test polaczenia przez `apimetod=test_auth_api` zweryfikowany na zywym koncie operatora; `ShipmentProviderRegistry` netkniety — `PolkurierShipmentService/TrackingService` w kolejnych fazach — Phase 127
- [x] polkurier ShipmentService + TrackingService + UI prepare panel: pelen kontrakt API (createShipment/getLabel/getStatus/cancelOrder/getAvailableCarriers), `PolkurierShipmentService` implementujacy `ShipmentProviderInterface` z normalizacja shipmenttype (lowercase) i splitem ulicy na street/housenumber/flatnumber, `PolkurierTrackingService` mapujacy statusy O/P/A/WP/D/Z/W na znormalizowane, panel "polkurier" w `prepare.php` z dynamiczna lista uslug z `available_carriers`, seed migracja `delivery_status_mappings(provider='polkurier')` z 7 wpisami z PDF v1.11; live test na #114/#115 zakonczony sukcesem po 4 iteracjach (ReferenceError → uppercase shipmenttype → orderno parsing → A4/A6); rozmiar etykiety sterowany w panelu klienta polkurier.pl (Ustawienia konta → Preferencje etykiet), NIE przez API — Phase 128 - [x] polkurier ShipmentService + TrackingService + UI prepare panel: pelen kontrakt API (createShipment/getLabel/getStatus/cancelOrder/getAvailableCarriers), `PolkurierShipmentService` implementujacy `ShipmentProviderInterface` z normalizacja shipmenttype (lowercase) i splitem ulicy na street/housenumber/flatnumber, `PolkurierTrackingService` mapujacy statusy O/P/A/WP/D/Z/W na znormalizowane, panel "polkurier" w `prepare.php` z dynamiczna lista uslug z `available_carriers`, seed migracja `delivery_status_mappings(provider='polkurier')` z 7 wpisami z PDF v1.11; live test na #114/#115 zakonczony sukcesem po 4 iteracjach (ReferenceError → uppercase shipmenttype → orderno parsing → A4/A6); rozmiar etykiety sterowany w panelu klienta polkurier.pl (Ustawienia konta → Preferencje etykiet), NIE przez API — Phase 128
- [x] Order User Notes module (Phase 129): pelen CRUD notatek autorskich operatora per zamowienie. Reuse `order_notes` przez nowy `note_type='user'` z `user_id` (FK→users SET NULL) + `author_name` (snapshot) + indeks `idx_order_notes_type_order`. `OrderNotesService` z autoryzacja DB-level (`WHERE user_id = :user_id`, rowCount=0 ⇒ 403). Sekcja `#notes` w "Wiadomosci i zalaczniki" w `/orders/{id}` z inline edit form + delete przez `OrderProAlerts.confirm`. Badge `[N]` (indigo neutralny) przy nr zamowienia na `/orders/list` (subquery `user_notes_count` w paginate). Brak admin override (brak systemu rol w aplikacji) — edit/delete tylko dla autora — Phase 129 - [x] Order User Notes module (Phase 129): pelen CRUD notatek autorskich operatora per zamowienie. Reuse `order_notes` przez nowy `note_type='user'` z `user_id` (FK→users SET NULL) + `author_name` (snapshot) + indeks `idx_order_notes_type_order`. `OrderNotesService` z autoryzacja DB-level (`WHERE user_id = :user_id`, rowCount=0 ⇒ 403). Sekcja `#notes` w "Wiadomosci i zalaczniki" w `/orders/{id}` z inline edit form + delete przez `OrderProAlerts.confirm`. Badge `[N]` (indigo neutralny) przy nr zamowienia na `/orders/list`; od Phase 144 badge korzysta z `notes_count` i liczy wszystkie rekordy `order_notes`, takze importowane ze zrodla. Brak admin override (brak systemu rol w aplikacji) — edit/delete tylko dla autora — Phase 129/144
- [x] polkurier delivery status mappings UI (Phase 130): polkurier jako 4. provider w dropdownie `/settings/delivery-statuses?tab=mapping`. `POLKURIER_MAP` + `POLKURIER_DESCRIPTIONS` w `DeliveryStatus.php` (7 wpisow O/P/A/WP/D/Z/W z oficjalnej dokumentacji v1.11, identyczne z migracja Phase 128 — DB seed staje sie no-op). `PROVIDERS` rozszerzone w `DeliveryStatusesController` + `DeliveryStatusMappingController`. `countAllUnmappedForBadge()` zlicza polkurier. Zero zmian w widoku (`_delivery-status-mappings-content.php` auto-iteruje po providerach z controllera) — Phase 130 - [x] polkurier delivery status mappings UI (Phase 130): polkurier jako 4. provider w dropdownie `/settings/delivery-statuses?tab=mapping`. `POLKURIER_MAP` + `POLKURIER_DESCRIPTIONS` w `DeliveryStatus.php` (7 wpisow O/P/A/WP/D/Z/W z oficjalnej dokumentacji v1.11, identyczne z migracja Phase 128 — DB seed staje sie no-op). `PROVIDERS` rozszerzone w `DeliveryStatusesController` + `DeliveryStatusMappingController`. `countAllUnmappedForBadge()` zlicza polkurier. Zero zmian w widoku (`_delivery-status-mappings-content.php` auto-iteruje po providerach z controllera) — Phase 130
### Deferred ### Deferred
@@ -325,6 +326,6 @@ Quick Reference:
--- ---
*PROJECT.md — Updated when requirements or context change* *PROJECT.md — Updated when requirements or context change*
*Last updated: 2026-05-18 after Phase 143 closure* *Last updated: 2026-05-18 after Phase 144 closure*

View File

@@ -6,6 +6,23 @@ orderPRO to narzedzie do wielokanalowego zarzadzania sprzedaza. Projekt przechod
## Current Milestone ## Current Milestone
v3.13 Imported Notes Badge Count Hotfix - Complete
Pilny hotfix dla listy zamowien: notatki zaimportowane ze zrodla, np. shopPRO, maja byc zliczane razem z notatkami autorskimi w badge `[N]` przy numerze zamowienia.
Progress: 1 of 1 phases complete (100%).
| Phase | Name | Plans | Status |
|-------|------|-------|--------|
| 144 | Imported Notes Badge Count Hotfix | 1/1 | Complete (2026-05-18; PHPUnit/Sonar env gaps documented) |
### Phase 144: Imported Notes Badge Count Hotfix
Focus: Zmienic licznik badge notatek na `/orders/list`, aby uzywal wszystkich rekordow `order_notes` dla zamowienia, a nie tylko `note_type='user'`. Zamowienie `1034` z importowana notatka shopPRO powinno pokazac cyfre na liscie.
Plans: 144-01 (complete; `.paul/phases/144-imported-notes-badge-count/144-01-SUMMARY.md`)
## Previous Milestone
v3.12 Orders List Sidebar UI Hotfix - Complete v3.12 Orders List Sidebar UI Hotfix - Complete
Maly hotfix UX dla ekranu operacyjnego: usuniecie opisowego boksu z listy zamowien oraz likwidacja widocznego "pokaz i schowaj" przy odswiezaniu strony ze zwinietym sidebarem. Maly hotfix UX dla ekranu operacyjnego: usuniecie opisowego boksu z listy zamowien oraz likwidacja widocznego "pokaz i schowaj" przy odswiezaniu strony ze zwinietym sidebarem.
@@ -21,7 +38,7 @@ Progress: 1 of 1 phases complete (100%).
Focus: Usunac boks "Zamowienia / Kompaktowa lista zamowien oparta o lokalna baze orderPRO." z `/orders/list` i zastosowac zapisany stan zwinietego sidebaru przed pierwszym renderem strony. Focus: Usunac boks "Zamowienia / Kompaktowa lista zamowien oparta o lokalna baze orderPRO." z `/orders/list` i zastosowac zapisany stan zwinietego sidebaru przed pierwszym renderem strony.
Plans: 143-01 (complete; `.paul/phases/143-orders-list-sidebar-ui-hotfix/143-01-SUMMARY.md`) Plans: 143-01 (complete; `.paul/phases/143-orders-list-sidebar-ui-hotfix/143-01-SUMMARY.md`)
## Previous Milestone ## Earlier Milestone
v3.11 Polkurier Shipment Prepare Hotfix - Complete v3.11 Polkurier Shipment Prepare Hotfix - Complete
@@ -670,4 +687,4 @@ Archive: `.paul/milestones/v0.1-ROADMAP.md`
--- ---
*Roadmap created: 2026-03-12* *Roadmap created: 2026-03-12*
*Last updated: 2026-05-18 - Phase 143 complete; v3.12 Orders List Sidebar UI Hotfix complete* *Last updated: 2026-05-18 - Phase 144 complete; v3.13 Imported Notes Badge Count Hotfix complete*

View File

@@ -5,19 +5,19 @@
See: .paul/PROJECT.md (updated 2026-05-18) See: .paul/PROJECT.md (updated 2026-05-18)
**Core value:** Sprzedawca moze obslugiwac zamowienia ze wszystkich kanalow sprzedazy i nadawac przesylki bez przelaczania sie miedzy platformami. **Core value:** Sprzedawca moze obslugiwac zamowienia ze wszystkich kanalow sprzedazy i nadawac przesylki bez przelaczania sie miedzy platformami.
**Current focus:** v3.12 Orders List Sidebar UI Hotfix complete; Phase 143 unified. **Current focus:** v3.13 Imported Notes Badge Count Hotfix complete; Phase 144 unified.
## Current Position ## Current Position
Milestone: v3.12 Orders List Sidebar UI Hotfix Milestone: v3.13 Imported Notes Badge Count Hotfix
Phase: 143 of 143 (Orders List Sidebar UI Hotfix) - Complete Phase: 144 of 144 (Imported Notes Badge Count Hotfix) - Complete
Plan: 143-01 complete Plan: 144-01 complete
Status: Milestone complete, ready for next milestone or release decision Status: Milestone complete, ready for next milestone or release decision
Last activity: 2026-05-18 11:50 - Unified .paul/phases/143-orders-list-sidebar-ui-hotfix/143-01-PLAN.md Last activity: 2026-05-18 12:39 - Unified .paul/phases/144-imported-notes-badge-count/144-01-PLAN.md
Progress: Progress:
- Milestone v3.12: [##########] 100% (1 of 1 phases complete) - Milestone v3.13: [##########] 100% (1 of 1 phases complete)
- Phase 143: [##########] 100% (complete) - Phase 144: [##########] 100% (complete)
## Loop Position ## Loop Position
@@ -29,19 +29,19 @@ PLAN -> APPLY -> UNIFY
## Session Continuity ## Session Continuity
Last session: 2026-05-18 11:50 Last session: 2026-05-18 12:39
Stopped at: Phase 143 complete; v3.12 milestone complete Stopped at: Phase 144 complete; v3.13 milestone complete
Next action: Run $paul-complete-milestone or start next milestone planning Next action: Run $paul-complete-milestone or start next milestone planning
Resume file: .paul/phases/143-orders-list-sidebar-ui-hotfix/143-01-SUMMARY.md Resume file: .paul/phases/144-imported-notes-badge-count/144-01-SUMMARY.md
## Pending parallel work ## Pending parallel work
- None — Phase 118, 121, 122 wszystkie zacommitowane (8f14851, 360eef1). - None — Phase 118, 121, 122 wszystkie zacommitowane (8f14851, 360eef1).
## Git State ## Git State
Last commit: HEAD fix(143): polish orders list and sidebar first paint Last commit: HEAD fix(144): count imported order notes in list badge
Last phase commit: HEAD fix(143): polish orders list and sidebar first paint Last phase commit: HEAD fix(144): count imported order notes in list badge
Previous: fix(142): preselect polkurier shipment mapping Previous: fix(143): polish orders list and sidebar first paint
Branch: main Branch: main
### Skill Audit (Phase 139) ### Skill Audit (Phase 139)
@@ -75,6 +75,12 @@ Branch: main
|----------|---------|-------| |----------|---------|-------|
| `sonar-scanner` | gap documented | Attempted after APPLY with `sonar-scanner --version`; CLI is not available in PATH. | | `sonar-scanner` | gap documented | Attempted after APPLY with `sonar-scanner --version`; CLI is not available in PATH. |
### Skill Audit (Phase 144)
| Expected | Invoked | Notes |
|----------|---------|-------|
| `sonar-scanner` | gap documented | Attempted after APPLY with `sonar-scanner --version`; CLI is not available in PATH. |
### Skill Audit (Phase 129) ### Skill Audit (Phase 129)
| Expected | Invoked | Notes | | Expected | Invoked | Notes |
@@ -133,6 +139,7 @@ Branch: main
### Recent Decisions ### Recent Decisions
- Phase 144 changed the `/orders/list` notes badge contract from operator-only notes to all `order_notes` rows; detail view grouping and note CRUD/import behavior remain unchanged.
- Phase 134 is documentation-only: no runtime code or schema changes were made. - Phase 134 is documentation-only: no runtime code or schema changes were made.
- Backlog entries are annotated, not deleted; stale/implemented cleanup is deferred to later phases. - Backlog entries are annotated, not deleted; stale/implemented cleanup is deferred to later phases.
- Phase 135 completed confirmed accounting net issues: `RECEIPT-NET-FIX` and `STAT-NET` are resolved for new/runtime behavior. - Phase 135 completed confirmed accounting net issues: `RECEIPT-NET-FIX` and `STAT-NET` are resolved for new/runtime behavior.
@@ -152,6 +159,7 @@ Branch: main
### Blockers / Concerns ### Blockers / Concerns
- Phase 144 APPLY: `vendor/bin/phpunit` is missing, so `tests/Unit/OrdersRepositoryNotesCountTest.php` was linted and covered by an ad-hoc SQLite runtime smoke instead of PHPUnit; `sonar-scanner` is unavailable in PATH.
- Phase 134: `sonar-scanner` is still unavailable in PATH. - Phase 134: `sonar-scanner` is still unavailable in PATH.
- Phase 135: `vendor/bin/phpunit` and `sonar-scanner` are unavailable in PATH/checkout; syntax checks and ad-hoc SQLite/runtime smoke passed. - Phase 135: `vendor/bin/phpunit` and `sonar-scanner` are unavailable in PATH/checkout; syntax checks and ad-hoc SQLite/runtime smoke passed.
- Phase 136: Fakturownia idempotency strategy implemented and UNIFY complete; runtime migration still needs local MySQL online. - Phase 136: Fakturownia idempotency strategy implemented and UNIFY complete; runtime migration still needs local MySQL online.

View File

@@ -20,6 +20,10 @@
- Dodano pre-hydration klasy `html.has-collapsed-sidebar`, aby zapisany zwiniety sidebar byl schowany od pierwszego renderu. - Dodano pre-hydration klasy `html.has-collapsed-sidebar`, aby zapisany zwiniety sidebar byl schowany od pierwszego renderu.
- Zachowano runtime toggle sidebaru i mobilne slide-in menu; pre-hydration compact state jest ograniczony do desktopu. - Zachowano runtime toggle sidebaru i mobilne slide-in menu; pre-hydration compact state jest ograniczony do desktopu.
- Gap: manualny smoke UI i SonarQube scan Phase 143 pozostaja do wykonania po uruchomieniu app/browser session i przywroceniu `sonar-scanner`. - Gap: manualny smoke UI i SonarQube scan Phase 143 pozostaja do wykonania po uruchomieniu app/browser session i przywroceniu `sonar-scanner`.
- [Phase 144, Plan 01] Naprawiono licznik badge notatek na `/orders/list`, aby obejmowal notatki autorskie i importowane ze zrodla.
- `OrdersRepository` zwraca `notes_count` liczony ze wszystkich rekordow `order_notes` dla zamowienia.
- Dodano test regresyjny `OrdersRepositoryNotesCountTest` i wykonano SQLite smoke `notes_count=2` dla notatki `message` + `user`.
- Gap: PHPUnit i SonarQube scan Phase 144 pozostaja do wykonania po przywroceniu `vendor/` i `sonar-scanner`.
## Zmienione pliki ## Zmienione pliki
@@ -45,9 +49,15 @@
- `.paul/phases/142-polkurier-shipment-prepare-prefill/142-01-SUMMARY.md` - `.paul/phases/142-polkurier-shipment-prepare-prefill/142-01-SUMMARY.md`
- `.paul/phases/143-orders-list-sidebar-ui-hotfix/143-01-PLAN.md` - `.paul/phases/143-orders-list-sidebar-ui-hotfix/143-01-PLAN.md`
- `.paul/phases/143-orders-list-sidebar-ui-hotfix/143-01-SUMMARY.md` - `.paul/phases/143-orders-list-sidebar-ui-hotfix/143-01-SUMMARY.md`
- `.paul/phases/144-imported-notes-badge-count/144-01-PLAN.md`
- `.paul/phases/144-imported-notes-badge-count/144-01-SUMMARY.md`
- `resources/views/layouts/app.php` - `resources/views/layouts/app.php`
- `resources/views/orders/list.php` - `resources/views/orders/list.php`
- `resources/views/shipments/prepare.php` - `resources/views/shipments/prepare.php`
- `resources/scss/app.scss` - `resources/scss/app.scss`
- `public/assets/css/app.css` - `public/assets/css/app.css`
- `tests/Unit/ShipmentPreparePolkurierMappingTest.php` - `tests/Unit/ShipmentPreparePolkurierMappingTest.php`
- `src/Modules/Orders/OrdersRepository.php`
- `src/Modules/Orders/OrdersController.php`
- `tests/Unit/OrdersRepositoryNotesCountTest.php`
- `DOCS/DB_SCHEMA.md`

View File

@@ -0,0 +1,179 @@
---
phase: 144-imported-notes-badge-count
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- src/Modules/Orders/OrdersRepository.php
- src/Modules/Orders/OrdersController.php
- tests/Unit/OrdersRepositoryNotesCountTest.php
- DOCS/ARCHITECTURE.md
- DOCS/DB_SCHEMA.md
- DOCS/TECH_CHANGELOG.md
autonomous: true
delegation: off
---
<objective>
## Goal
Naprawic licznik notatek na `/orders/list`, aby badge `[N]` przy numerze zamowienia zliczal wszystkie notatki z `order_notes` dla zamowienia: autorskie `note_type='user'` oraz importowane ze zrodla, np. shopPRO `note_type='message'`.
## Purpose
Operator widzi na liscie zamowien, ze zamowienie wymaga uwagi lub zawiera wiadomosc klienta, bez wchodzenia w szczegoly. Obecnie importowana notatka z shopPRO w zamowieniu `1034` jest widoczna w szczegolach, ale nie podbija liczby na liscie.
## Output
Behavior-preserving hotfix w module Orders: zmieniony count subquery i nazewnictwo pola w row/controller, test regresyjny dla importowanych notatek oraz aktualizacja dokumentacji technicznej.
</objective>
<context>
<clarifications>
- No clarifications needed - proceeding. Uzytkownik jednoznacznie wskazal oczekiwane zachowanie: importowane notatki z shopPRO maja byc zliczane do notatek orderPRO i widoczne jako cyfra na liscie zamowien.
</clarifications>
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
@.paul/STATE.md
@.paul/codebase/architecture.md
@.paul/codebase/db_schema.md
@AGENTS.md
## Source Files
@src/Modules/Orders/OrdersRepository.php
@src/Modules/Orders/OrdersController.php
@src/Modules/Orders/OrderNotesService.php
@src/Modules/Orders/OrderImportRepository.php
@resources/views/orders/show.php
@resources/scss/modules/_order-notes.scss
@tests/bootstrap.php
@DOCS/ARCHITECTURE.md
@DOCS/DB_SCHEMA.md
@DOCS/TECH_CHANGELOG.md
</context>
<skills>
## Required Skills / Checks
| Skill | Priority | When to Invoke | Loaded? |
|-------|----------|----------------|---------|
| sonar-scanner | required | Po APPLY, przed UNIFY, jezeli CLI jest dostepny | ○ |
Note: `.paul/SPECIAL-FLOWS.md` wymaga skanu Sonar po APPLY. Historycznie CLI bywa niedostepny; jezeli nadal go nie ma, udokumentowac gap w SUMMARY/STATE.
</skills>
<acceptance_criteria>
## AC-1: Importowana notatka podbija badge
```gherkin
Given zamowienie ma co najmniej jedna notatke w order_notes z note_type innym niz "user"
When operator otwiera /orders/list
Then przy numerze zamowienia widzi badge [N], gdzie N obejmuje te importowane notatki
```
## AC-2: Notatki autorskie nadal sa liczone
```gherkin
Given zamowienie ma notatki autorskie note_type="user"
When operator otwiera /orders/list
Then badge [N] nadal obejmuje notatki autorskie i linkuje do /orders/{id}#notes
```
## AC-3: Licznik jest suma wszystkich notatek zamowienia
```gherkin
Given zamowienie ma jedna notatke autorska i jedna importowana
When lista zamowien renderuje kolumne numeru
Then wyswietlany badge pokazuje [2], a title odmienia liczbe jak dotychczas
```
## AC-4: Brak zmian schematu
```gherkin
Given obecny schemat ma tabele order_notes i indeks order_notes_order_idx
When hotfix jest wdrazany
Then nie powstaje nowa migracja ani nowa kolumna, bo problem dotyczy tylko zapytania listy
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: Zmienic licznik listy na wszystkie notatki</name>
<files>src/Modules/Orders/OrdersRepository.php, src/Modules/Orders/OrdersController.php</files>
<action>
W `OrdersRepository::buildListSql()` zastapic `user_notes_count` licznikiem wszystkich rekordow `order_notes` danego zamowienia.
- Zmienic prywatny helper z semantyki `userNotesCountSubquerySql()` na neutralne `notesCountSubquerySql()`.
- Query ma liczyc `COUNT(*) FROM order_notes WHERE order_id = o.id`, bez filtra `note_type`.
- W `transformOrderRow()` zwracac `notes_count`.
- W `OrdersController::buildRow()` czytac `notes_count`; title i link badge pozostaja takie jak dotychczas.
- Unikac zmiany sekcji szczegolow zamowienia: importowane i autorskie notatki nadal sa tam renderowane osobno.
</action>
<verify>php -l src/Modules/Orders/OrdersRepository.php && php -l src/Modules/Orders/OrdersController.php</verify>
<done>AC-1, AC-2 i AC-3 spelnione: badge bazuje na lacznej liczbie notatek.</done>
</task>
<task type="auto">
<name>Task 2: Dodac test regresyjny licznika notatek</name>
<files>tests/Unit/OrdersRepositoryNotesCountTest.php</files>
<action>
Dodac test jednostkowy pokrywajacy nowa semantyke licznika.
- Utworzyc minimalna baze SQLite in-memory z tabelami wymaganymi przez `OrdersRepository::paginate()`.
- Zaseedowac zamowienie z jedna notatka `note_type='message'` i jedna `note_type='user'`.
- Wywolac `paginate(['page' => 1, 'per_page' => 20])` i potwierdzic, ze pierwszy wiersz ma `notes_count === 2`.
- Dodac drugi przypadek lub asercje dla zamowienia bez notatek: `notes_count === 0`.
- Nie testowac widoku szczegolow ani CRUD notatek autorskich, bo to istnieje poza zakresem tego hotfixa.
</action>
<verify>vendor/bin/phpunit tests/Unit/OrdersRepositoryNotesCountTest.php albo, jezeli vendor/ nadal nie istnieje, php -l tests/Unit/OrdersRepositoryNotesCountTest.php</verify>
<done>AC-1, AC-2 i AC-3 maja automatyczna regresje na poziomie repozytorium.</done>
</task>
<task type="auto">
<name>Task 3: Zaktualizowac dokumentacje techniczna</name>
<files>DOCS/ARCHITECTURE.md, DOCS/DB_SCHEMA.md, DOCS/TECH_CHANGELOG.md</files>
<action>
Udokumentowac hotfix bez sugerowania zmiany schematu.
- `DOCS/ARCHITECTURE.md`: dopisac przy module Orders/list, ze badge notatek zlicza wszystkie `order_notes`, a szczegoly nadal rozdzielaja autorskie i importowane notatki.
- `DOCS/DB_SCHEMA.md`: przy `order_notes` doprecyzowac, ze indeks `order_notes_order_idx` wspiera laczny licznik notatek na liscie; `idx_order_notes_type_order` zostaje dla list user/import.
- `DOCS/TECH_CHANGELOG.md`: dodac wpis 2026-05-18 z opisem co i dlaczego.
</action>
<verify>rg -n "notes_count|badge|order_notes" DOCS/ARCHITECTURE.md DOCS/DB_SCHEMA.md DOCS/TECH_CHANGELOG.md</verify>
<done>AC-4 spelnione i dokumentacja zgadza sie z nowa semantyka.</done>
</task>
</tasks>
<boundaries>
## DO NOT CHANGE
- database/migrations/* - brak migracji w tym hotfixie.
- src/Modules/Orders/OrderImportRepository.php - import notatek dziala; problem jest w liczniku listy.
- src/Modules/Orders/OrderNotesService.php - CRUD notatek autorskich bez zmian.
- resources/views/orders/show.php - szczegoly rozdzielaja notatki autorskie/importowane i to zostaje.
## SCOPE LIMITS
- Nie zmieniac wygladu badge, kolorow ani SCSS.
- Nie laczyc UI sekcji notatek w szczegolach zamowienia.
- Nie dodawac filtrow po notatkach ani nowych endpointow.
- Nie wykonywac operacji na zdalnej bazie poza ewentualna read-only weryfikacja po akceptacji.
</boundaries>
<verification>
Before declaring plan complete:
- [ ] `php -l src/Modules/Orders/OrdersRepository.php`
- [ ] `php -l src/Modules/Orders/OrdersController.php`
- [ ] `php -l tests/Unit/OrdersRepositoryNotesCountTest.php`
- [ ] `vendor/bin/phpunit tests/Unit/OrdersRepositoryNotesCountTest.php` albo udokumentowany brak `vendor/`
- [ ] `rg -n "user_notes_count|notes_count" src/Modules/Orders tests DOCS`
- [ ] All acceptance criteria met
</verification>
<success_criteria>
- Lista zamowien pokazuje badge dla zamowien majacych tylko importowana notatke.
- Zamowienia z mieszanka notatek autorskich i importowanych pokazuja sume.
- Brak migracji DB i brak zmian w import flow.
- Dokumentacja techniczna opisuje nowy kontrakt licznika.
</success_criteria>
<output>
After completion, create `.paul/phases/144-imported-notes-badge-count/144-01-SUMMARY.md`.
</output>

View File

@@ -0,0 +1,158 @@
---
phase: 144-imported-notes-badge-count
plan: 01
subsystem: orders
tags: [orders-list, order-notes, badge, shoppro]
requires:
- phase: 129-order-user-notes
provides: shared `order_notes` table for imported and operator notes
provides:
- Combined `/orders/list` notes badge count for imported and operator notes
- Regression coverage for `OrdersRepository::paginate()` notes count
affects: [orders-list, order-notes, shoppro-import]
tech-stack:
added: []
patterns: [correlated count subquery, sqlite repository smoke]
key-files:
created:
- tests/Unit/OrdersRepositoryNotesCountTest.php
modified:
- src/Modules/Orders/OrdersRepository.php
- src/Modules/Orders/OrdersController.php
- DOCS/ARCHITECTURE.md
- DOCS/DB_SCHEMA.md
- DOCS/TECH_CHANGELOG.md
key-decisions:
- "Notes badge counts every `order_notes` row; details view still separates user/imported notes."
patterns-established:
- "Use `notes_count` for combined order notes counters; reserve note_type filters for detail sections and CRUD ownership."
duration: 20min
started: 2026-05-18T12:19:00+02:00
completed: 2026-05-18T12:39:00+02:00
---
# Phase 144 Plan 01: Imported Notes Badge Count Hotfix Summary
`/orders/list` now shows the notes badge for orders that only have imported source notes, including shopPRO messages.
## Performance
| Metric | Value |
|--------|-------|
| Duration | ~20 minutes |
| Started | 2026-05-18T12:19:00+02:00 |
| Completed | 2026-05-18T12:39:00+02:00 |
| Tasks | 3 completed |
| Files modified | 8 planned files plus PAUL state/changelog |
## Acceptance Criteria Results
| Criterion | Status | Notes |
|-----------|--------|-------|
| AC-1: Importowana notatka podbija badge | Pass | `OrdersRepository::notesCountSubquerySql()` counts all `order_notes` rows without filtering `note_type`. |
| AC-2: Notatki autorskie nadal sa liczone | Pass | Operator notes remain rows in `order_notes`, so they are included in the same count. |
| AC-3: Licznik jest suma wszystkich notatek zamowienia | Pass | Added repository regression test and ad-hoc SQLite smoke where `message + user = notes_count 2`. |
| AC-4: Brak zmian schematu | Pass | No migration added; existing `order_notes` table and `order_notes_order_idx` are used. |
## Accomplishments
- Replaced list-row `user_notes_count` semantics with combined `notes_count`.
- Kept the existing badge markup, link to `#notes`, and title pluralization behavior.
- Added `OrdersRepositoryNotesCountTest` for combined imported/operator notes and zero-note orders.
- Updated architecture, schema documentation, and technical changelog for the new list badge contract.
## Task Commits
Commits are handled at phase transition time.
| Task | Commit | Type | Description |
|------|--------|------|-------------|
| Task 1: Zmienic licznik listy na wszystkie notatki | pending | fix | `OrdersRepository` now selects `notes_count`; `OrdersController` renders it. |
| Task 2: Dodac test regresyjny licznika notatek | pending | test | Added SQLite repository test for imported plus user notes. |
| Task 3: Zaktualizowac dokumentacje techniczna | pending | docs | Documented combined badge count and no-schema-change scope. |
## Files Created/Modified
| File | Change | Purpose |
|------|--------|---------|
| `src/Modules/Orders/OrdersRepository.php` | Modified | Count all notes for list rows via `notesCountSubquerySql()`. |
| `src/Modules/Orders/OrdersController.php` | Modified | Render badge from `notes_count`. |
| `tests/Unit/OrdersRepositoryNotesCountTest.php` | Created | Regression coverage for combined notes count. |
| `DOCS/ARCHITECTURE.md` | Modified | Documented `/orders/list` notes badge contract. |
| `DOCS/DB_SCHEMA.md` | Modified | Documented `order_notes` and indexes relevant to the badge. |
| `DOCS/TECH_CHANGELOG.md` | Modified | Added Phase 144 technical changelog entry. |
| `.paul/STATE.md` | Modified | Recorded APPLY and verification gaps. |
| `.paul/ROADMAP.md` | Modified | Added Phase 144 status. |
## Decisions Made
| Decision | Rationale | Impact |
|----------|-----------|--------|
| Count all `order_notes` rows for the badge | User expectation is that imported shopPRO notes are operationally visible on the list just like operator notes. | Orders with only imported notes now display `[N]` on `/orders/list`. |
| Keep details view grouping unchanged | User asked only for list count; existing detail UI separates operator notes from source messages clearly. | No UI/SCSS changes and no behavior change for note CRUD/import. |
## Deviations from Plan
### Summary
| Type | Count | Impact |
|------|-------|--------|
| Auto-fixed | 1 | Renamed one leftover variable reference during Task 1; no behavior risk. |
| Scope additions | 0 | None. |
| Deferred | 2 | Environment gaps only. |
### Auto-fixed Issues
**1. Variable rename cleanup**
- **Found during:** Task 1
- **Issue:** After renaming `$userNotesCount` to `$notesCount`, the badge title still referenced the old variable.
- **Fix:** Updated title construction to use `$notesCount`.
- **Files:** `src/Modules/Orders/OrdersController.php`
- **Verification:** PHP lint and `rg` confirmed no old source references remain.
### Deferred Items
- `PHPUNIT-MISSING-144`: `vendor/bin/phpunit` is absent in the checkout, so the PHPUnit test was linted and an equivalent SQLite runtime smoke was executed.
- `SONAR-MISSING-144`: `sonar-scanner` is not available in PATH, so the required scan could not run.
## Issues Encountered
| Issue | Resolution |
|-------|------------|
| `vendor/bin/phpunit` missing | Ran `php -l` for the test and an ad-hoc SQLite smoke through `OrdersRepository::paginate()`. |
| `sonar-scanner` missing in PATH | Documented gap in STATE/SUMMARY. |
## Verification Results
| Command | Result |
|---------|--------|
| `C:\xampp\php\php.exe -l src\Modules\Orders\OrdersRepository.php` | Pass |
| `C:\xampp\php\php.exe -l src\Modules\Orders\OrdersController.php` | Pass |
| `C:\xampp\php\php.exe -l tests\Unit\OrdersRepositoryNotesCountTest.php` | Pass |
| `vendor/bin/phpunit tests/Unit/OrdersRepositoryNotesCountTest.php` | Not run: `vendor/bin/phpunit` missing |
| Ad-hoc SQLite smoke for `message + user` notes | Pass: `notes_count smoke OK: 2` |
| `git diff --check` | Pass |
| `sonar-scanner --version` | Not run: command unavailable |
## Skill Audit
| Expected | Invoked | Notes |
|----------|---------|-------|
| `sonar-scanner` | gap documented | CLI is unavailable in PATH. |
## Next Phase Readiness
**Ready:**
- The Phase 144 hotfix is complete and documented.
- Future order list counters should use `notes_count` when they mean all notes.
**Concerns:**
- PHPUnit still requires restoring `vendor/` or project dependencies.
- Sonar still requires restoring `sonar-scanner` in PATH or a fallback scanner.
**Blockers:**
- None for this hotfix.
---
*Phase: 144-imported-notes-badge-count, Plan: 01*
*Completed: 2026-05-18*

View File

@@ -109,6 +109,7 @@ HTTP Request
### Orders List and Sidebar State ### Orders List and Sidebar State
- `/orders/list` renders the reusable order status panel and shared `components/table-list` directly; the previous descriptive intro card was removed so the operational table starts higher on the screen. - `/orders/list` renders the reusable order status panel and shared `components/table-list` directly; the previous descriptive intro card was removed so the operational table starts higher on the screen.
- The order number cell shows the notes badge from `OrdersRepository::notesCountSubquerySql()`, counting every `order_notes` row for the order. Imported source notes (`note_type <> 'user'`) and operator notes (`note_type='user'`) both contribute to the same `[N]` badge, while order details still render those groups separately.
- The desktop sidebar collapse state is stored in `localStorage.sidebarCollapsed`. - The desktop sidebar collapse state is stored in `localStorage.sidebarCollapsed`.
- `resources/views/layouts/app.php` reads that value in the document head and adds `html.has-collapsed-sidebar` before CSS loads. `resources/scss/app.scss` mirrors the compact sidebar rules for that pre-hydration class, so a saved collapsed sidebar is collapsed on first paint instead of animating after the footer script runs. - `resources/views/layouts/app.php` reads that value in the document head and adds `html.has-collapsed-sidebar` before CSS loads. `resources/scss/app.scss` mirrors the compact sidebar rules for that pre-hydration class, so a saved collapsed sidebar is collapsed on first paint instead of animating after the footer script runs.
- The footer sidebar script still owns runtime interactions: it applies/removes `.sidebar.is-collapsed`, updates the button labels, closes open `details`, persists the state, and then removes the temporary HTML pre-hydration class. - The footer sidebar script still owns runtime interactions: it applies/removes `.sidebar.is-collapsed`, updates the button labels, closes open `details`, persists the state, and then removes the temporary HTML pre-hydration class.

View File

@@ -324,6 +324,24 @@ UNIQUE: `(integration_id, external_order_id)`
UNIQUE: `(order_id, source_payment_id)` UNIQUE: `(order_id, source_payment_id)`
**order_notes** — Notes attached to orders, both imported from source systems and written by operators
| Column | Type | Nullable | Notes |
|--------|------|----------|-------|
| `id` | BIGINT UNSIGNED | NO | PK, AUTO_INCREMENT |
| `order_id` | BIGINT UNSIGNED | NO | FK -> orders(id) CASCADE |
| `source_note_id` | VARCHAR(64) | YES | Source note ID; NULL for operator notes |
| `note_type` | VARCHAR(32) | NO | Imported types such as `shoppro`/`allegro`/`message`, or `user` for operator notes |
| `user_id` | INT UNSIGNED | YES | FK -> users(id) SET NULL; set for operator notes |
| `author_name` | VARCHAR(190) | YES | Snapshot of user name for operator notes |
| `created_at_external` | DATETIME | YES | Source timestamp for imported notes |
| `comment` | TEXT | NO | Note body |
| `payload_json` | JSON | YES | Raw source payload for imported notes |
| `created_at` | DATETIME | NO | DEFAULT CURRENT_TIMESTAMP |
| `updated_at` | DATETIME | NO | DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
UNIQUE: `(order_id, source_note_id)`; MySQL allows multiple NULL `source_note_id` values for operator notes.
Indexes: `order_notes_order_idx (order_id)` supports the combined notes badge on `/orders/list`; `idx_order_notes_type_order (note_type, order_id)` supports user/imported note lists.
--- ---
## Order Statuses ## Order Statuses

View File

@@ -1,5 +1,19 @@
# Technical Changelog # Technical Changelog
## 2026-05-18 - Phase 144 Plan 01: Imported Notes Badge Count Hotfix
**Co zrobiono:**
- Zmieniono licznik badge notatek na `/orders/list` z `user_notes_count` na `notes_count`.
- `OrdersRepository` liczy teraz wszystkie rekordy `order_notes` dla zamowienia, bez filtra `note_type='user'`.
- `OrdersController` renderuje ten sam badge `[N]` i link do `#notes`, ale liczba obejmuje notatki autorskie oraz importowane ze zrodla, np. shopPRO `message`.
- Dodano test regresyjny `OrdersRepositoryNotesCountTest` dla sumy notatki importowanej i autorskiej oraz zamowienia bez notatek.
**Dlaczego:**
- Zamowienie z notatka zaimportowana z shopPRO bylo poprawnie widoczne w szczegolach, ale lista zamowien nie pokazywala cyfry, bo licznik obejmowal tylko notatki operatora.
**BREAKING / migracja:**
- Brak migracji DB i brak zmian breaking. Hotfix zmienia tylko zapytanie listy zamowien i dokumentuje istniejaca tabele `order_notes`.
## 2026-05-18 - Phase 143 Plan 01: Orders List Sidebar UI Hotfix ## 2026-05-18 - Phase 143 Plan 01: Orders List Sidebar UI Hotfix
**Co zrobiono:** **Co zrobiono:**

View File

@@ -795,11 +795,11 @@ final class OrdersController
? ' <span class="risk-return-badge" title="Klient nie odebral ' . $returnedCount . ' przesylek w historii">zwroty: ' . $returnedCount . '</span>' ? ' <span class="risk-return-badge" title="Klient nie odebral ' . $returnedCount . ' przesylek w historii">zwroty: ' . $returnedCount . '</span>'
: ''; : '';
$userNotesCount = max(0, (int) ($row['user_notes_count'] ?? 0)); $notesCount = max(0, (int) ($row['notes_count'] ?? 0));
$notesBadge = $userNotesCount >= 1 $notesBadge = $notesCount >= 1
? ' <a href="/orders/' . (int) ($row['id'] ?? 0) . '#notes" class="order-notes-badge" title="' . $userNotesCount . ' ' ? ' <a href="/orders/' . (int) ($row['id'] ?? 0) . '#notes" class="order-notes-badge" title="' . $notesCount . ' '
. ($userNotesCount === 1 ? 'notatka' : ($userNotesCount < 5 ? 'notatki' : 'notatek')) . '">[' . ($notesCount === 1 ? 'notatka' : ($notesCount < 5 ? 'notatki' : 'notatek')) . '">['
. $userNotesCount . ']</a>' . $notesCount . ']</a>'
: ''; : '';
$previewBtn = '<button type="button" class="btn-icon js-order-preview-btn" data-order-id="' . (int) ($row['id'] ?? 0) . '" title="Podglad">' $previewBtn = '<button type="button" class="btn-icon js-order-preview-btn" data-order-id="' . (int) ($row['id'] ?? 0) . '" title="Podglad">'

View File

@@ -183,7 +183,7 @@ final class OrdersRepository
COALESCE(od_agg.documents_count, 0) AS documents_count, COALESCE(od_agg.documents_count, 0) AS documents_count,
ig.name AS integration_name, ig.name AS integration_name,
' . $this->customerReturnedCountSubquerySql('o', 'a') . ' AS customer_returned_count, ' . $this->customerReturnedCountSubquerySql('o', 'a') . ' AS customer_returned_count,
' . $this->userNotesCountSubquerySql('o') . ' AS user_notes_count ' . $this->notesCountSubquerySql('o') . ' AS notes_count
FROM orders o FROM orders o
LEFT JOIN order_addresses a ON a.order_id = o.id AND a.address_type = "customer" 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.status_code) = asm.allegro_status_code LEFT JOIN allegro_order_status_mappings asm ON o.source = "allegro" AND LOWER(o.status_code) = asm.allegro_status_code
@@ -247,7 +247,7 @@ final class OrdersRepository
'projects_done' => (int) ($row['projects_done'] ?? 0), 'projects_done' => (int) ($row['projects_done'] ?? 0),
'projects_total' => (int) ($row['projects_total'] ?? 0), 'projects_total' => (int) ($row['projects_total'] ?? 0),
'customer_returned_count' => max(0, (int) ($row['customer_returned_count'] ?? 0)), 'customer_returned_count' => max(0, (int) ($row['customer_returned_count'] ?? 0)),
'user_notes_count' => max(0, (int) ($row['user_notes_count'] ?? 0)), 'notes_count' => max(0, (int) ($row['notes_count'] ?? 0)),
]; ];
} }
@@ -714,13 +714,13 @@ final class OrdersRepository
} }
/** /**
* Phase 129-01: subquery liczby notatek autorskich (note_type='user') dla zamowienia. * Subquery liczby wszystkich notatek zamowienia, autorskich i importowanych.
* Wspierane indeksem idx_order_notes_type_order (note_type, order_id). * Wspierane indeksem order_notes_order_idx (order_id).
*/ */
private function userNotesCountSubquerySql(string $orderAlias): string private function notesCountSubquerySql(string $orderAlias): string
{ {
return '(SELECT COUNT(*) FROM order_notes return '(SELECT COUNT(*) FROM order_notes
WHERE order_id = ' . $orderAlias . '.id AND note_type = "user")'; WHERE order_id = ' . $orderAlias . '.id)';
} }
private function effectiveStatusSql(string $orderAlias, string $mappingAlias): string private function effectiveStatusSql(string $orderAlias, string $mappingAlias): string

View File

@@ -0,0 +1,174 @@
<?php
declare(strict_types=1);
namespace Tests\Unit;
use App\Modules\Orders\OrdersRepository;
use PDO;
use PHPUnit\Framework\TestCase;
use ReflectionProperty;
final class OrdersRepositoryNotesCountTest extends TestCase
{
private PDO $pdo;
private OrdersRepository $repository;
protected function setUp(): void
{
$this->pdo = new PDO('sqlite::memory:');
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->pdo->sqliteCreateFunction('REGEXP_REPLACE', static fn (string $value): string => preg_replace('/[^0-9]+/', '', $value) ?? '');
$this->createSchema();
$this->repository = new OrdersRepository($this->pdo);
$supportsMappedMedia = new ReflectionProperty(OrdersRepository::class, 'supportsMappedMedia');
$supportsMappedMedia->setAccessible(true);
$supportsMappedMedia->setValue(null, false);
}
public function testImportedAndUserNotesAreCountedTogether(): void
{
$this->seedOrder(1, 'OP/1');
$this->seedNote(1, 'message', 'Prosze o szybka wysylke');
$this->seedNote(1, 'user', 'Sprawdzic przed pakowaniem');
$result = $this->repository->paginate(['page' => 1, 'per_page' => 20]);
self::assertSame('', $result['error']);
self::assertSame(1, $result['total']);
self::assertSame(2, $result['items'][0]['notes_count'] ?? null);
}
public function testOrderWithoutNotesReturnsZeroCount(): void
{
$this->seedOrder(2, 'OP/2');
$result = $this->repository->paginate(['page' => 1, 'per_page' => 20]);
self::assertSame('', $result['error']);
self::assertSame(1, $result['total']);
self::assertSame(0, $result['items'][0]['notes_count'] ?? null);
}
private function createSchema(): void
{
$this->pdo->exec(
'CREATE TABLE orders (
id INTEGER PRIMARY KEY,
internal_order_number TEXT,
source TEXT,
source_order_id TEXT,
external_order_id TEXT,
status_code TEXT,
payment_status INTEGER,
currency TEXT,
total_with_tax REAL,
total_paid REAL,
ordered_at TEXT,
source_created_at TEXT,
source_updated_at TEXT,
fetched_at TEXT,
is_canceled_by_buyer INTEGER DEFAULT 0,
external_carrier_id TEXT,
external_payment_type_id TEXT,
integration_id INTEGER,
customer_login TEXT
)'
);
$this->pdo->exec(
'CREATE TABLE order_addresses (
order_id INTEGER,
address_type TEXT,
name TEXT,
email TEXT,
phone TEXT,
city TEXT
)'
);
$this->pdo->exec(
'CREATE TABLE allegro_order_status_mappings (
allegro_status_code TEXT,
orderpro_status_code TEXT
)'
);
$this->pdo->exec(
'CREATE TABLE integrations (
id INTEGER PRIMARY KEY,
name TEXT
)'
);
$this->pdo->exec(
'CREATE TABLE order_items (
id INTEGER PRIMARY KEY,
order_id INTEGER,
original_name TEXT,
quantity REAL,
media_url TEXT,
sort_order INTEGER,
project_generated INTEGER DEFAULT 0
)'
);
$this->pdo->exec(
'CREATE TABLE order_shipments (
order_id INTEGER
)'
);
$this->pdo->exec(
'CREATE TABLE order_documents (
order_id INTEGER
)'
);
$this->pdo->exec(
'CREATE TABLE shipment_packages (
order_id INTEGER,
delivery_status TEXT
)'
);
$this->pdo->exec(
'CREATE TABLE order_notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
order_id INTEGER,
note_type TEXT,
comment TEXT
)'
);
}
private function seedOrder(int $id, string $number): void
{
$this->pdo->prepare(
'INSERT INTO orders (
id, internal_order_number, source, source_order_id, external_order_id, status_code,
payment_status, currency, total_with_tax, total_paid, ordered_at, source_created_at,
source_updated_at, fetched_at, integration_id
) VALUES (
:id, :internal_order_number, "shoppro", :source_order_id, :external_order_id, "nowe",
2, "PLN", 100.00, 100.00, "2026-05-18 10:00:00", "2026-05-18 10:00:00",
"2026-05-18 10:00:00", "2026-05-18 10:00:00", 1
)'
)->execute([
'id' => $id,
'internal_order_number' => $number,
'source_order_id' => 'SP/' . $id,
'external_order_id' => 'EXT/' . $id,
]);
$this->pdo->prepare(
'INSERT INTO order_addresses (order_id, address_type, name, email, phone, city)
VALUES (:order_id, "customer", "Jan Testowy", "jan@example.test", "500600700", "Rzeszow")'
)->execute(['order_id' => $id]);
}
private function seedNote(int $orderId, string $noteType, string $comment): void
{
$this->pdo->prepare(
'INSERT INTO order_notes (order_id, note_type, comment)
VALUES (:order_id, :note_type, :comment)'
)->execute([
'order_id' => $orderId,
'note_type' => $noteType,
'comment' => $comment,
]);
}
}