update
This commit is contained in:
@@ -71,6 +71,7 @@ Sprzedawca może obsługiwać zamówienia ze wszystkich kanałów
|
||||
- [x] Automatyzacja: event `order.status_aged` (cron) + warunek `days_in_status` — Phase 60
|
||||
- [x] Aktywacja przycisku Platnosc w headerze zamowienia + poprawa odstepu w formularzu platnosci — Phase 61
|
||||
- [x] Ochrona danych lokalnych przy re-imporcie + rozroznienie import/aktualizacja w activity log shopPRO — Phase 62
|
||||
- [x] Import i wyswietlanie personalizacji produktow z shopPRO (custom_fields) + naprawa daty zamowienia — Phase 63
|
||||
|
||||
### Active (In Progress)
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ Wersja mobilna aplikacji, modul po module. Cel: pelna uzywalnosc orderPRO na tel
|
||||
| 60 | Order Status Aged Event | 1/1 | Complete |
|
||||
| 61 | Payment Button Activation | 1/1 | Complete |
|
||||
| 62 | Import Re-import Safety | 1/1 | Complete |
|
||||
| 63 | Order Item Personalization | 1/1 | Complete |
|
||||
| TBD | Mobile Orders List | - | Not started |
|
||||
| TBD | Mobile Order Details | - | Not started |
|
||||
| TBD | Mobile Settings | - | Not started |
|
||||
|
||||
@@ -5,19 +5,19 @@
|
||||
See: .paul/PROJECT.md (updated 2026-03-31)
|
||||
|
||||
**Core value:** Sprzedawca moze obslugiwac zamowienia ze wszystkich kanalow sprzedazy i nadawac przesylki bez przelaczania sie miedzy platformami.
|
||||
**Current focus:** Milestone v3.0 — Phase 62 complete, ready for next PLAN
|
||||
**Current focus:** Milestone v3.0 — Phase 63 complete, ready for next PLAN
|
||||
|
||||
## Current Position
|
||||
|
||||
Milestone: v3.0 Mobile Responsive — In progress
|
||||
Phase: 11 of N (62 - Import Re-import Safety) — Complete
|
||||
Plan: 62-01 complete
|
||||
Status: Loop complete — phase 62 done, ready for next PLAN
|
||||
Last activity: 2026-03-31 — UNIFY closed for 62-01
|
||||
Phase: 12 of N (63 - Order Item Personalization) — Complete
|
||||
Plan: 63-01 complete
|
||||
Status: Loop complete — phase 63 done, ready for next PLAN
|
||||
Last activity: 2026-04-01 — UNIFY closed for 63-01
|
||||
|
||||
Progress:
|
||||
- Milestone: [######░░░░] ~58%
|
||||
- Phase 62: [##########] 100%
|
||||
- Milestone: [######░░░░] ~62%
|
||||
- Phase 63: [##########] 100%
|
||||
|
||||
## Loop Position
|
||||
|
||||
@@ -29,13 +29,13 @@ PLAN ──▶ APPLY ──▶ UNIFY
|
||||
|
||||
## Session Continuity
|
||||
|
||||
Last session: 2026-03-31
|
||||
Stopped at: Phase 62 complete
|
||||
Last session: 2026-04-01
|
||||
Stopped at: Phase 63 complete
|
||||
Next action: /paul:plan dla kolejnego modulu
|
||||
Resume file: .paul/phases/62-import-reimport-safety/62-01-SUMMARY.md
|
||||
Resume file: .paul/phases/63-order-item-personalization/63-01-SUMMARY.md
|
||||
|
||||
## Git State
|
||||
|
||||
Last commit: af48e84
|
||||
Last commit: 34b0a2b
|
||||
Branch: main
|
||||
Feature branches merged: none
|
||||
|
||||
164
.paul/phases/63-order-item-personalization/63-01-PLAN.md
Normal file
164
.paul/phases/63-order-item-personalization/63-01-PLAN.md
Normal file
@@ -0,0 +1,164 @@
|
||||
---
|
||||
phase: 63-order-item-personalization
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- database/migrations/20260401_000063_add_personalization_to_order_items.sql
|
||||
- src/Modules/Settings/ShopproOrderMapper.php
|
||||
- src/Modules/Orders/OrderImportRepository.php
|
||||
- resources/views/orders/show.php
|
||||
- resources/scss/orders/_show.scss
|
||||
autonomous: true
|
||||
---
|
||||
|
||||
<objective>
|
||||
## Goal
|
||||
Pobieranie danych personalizacji produktów z shopPRO i wyświetlanie ich w szczegółach zamówienia orderPRO.
|
||||
|
||||
## Purpose
|
||||
Sprzedawcy widzą personalizacje klientów (np. tekst grawerunku, link Spotify, dedykacja) bezpośrednio w orderPRO bez konieczności logowania do shopPRO. Kluczowe dla realizacji zamówień z personalizowanymi produktami.
|
||||
|
||||
## Output
|
||||
- Migracja DB: kolumna `personalization` w `order_items`
|
||||
- Mapper: ekstrakcja `custom_fields` z odpowiedzi shopPRO API
|
||||
- UI: wyświetlanie personalizacji pod nazwą produktu w widoku zamówienia
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
## Project Context
|
||||
@.paul/PROJECT.md
|
||||
@.paul/ROADMAP.md
|
||||
@.paul/STATE.md
|
||||
|
||||
## Source Files
|
||||
@src/Modules/Settings/ShopproOrderMapper.php — mapItems() linia 527, mapuje produkty z API shopPRO
|
||||
@src/Modules/Orders/OrderImportRepository.php — replaceItems() wstawia pozycje do DB
|
||||
@resources/views/orders/show.php — widok szczegółów zamówienia, sekcja produktów
|
||||
@database/migrations/20260302_000018_create_orders_tables_and_schedule.sql — schemat order_items
|
||||
</context>
|
||||
|
||||
<skills>
|
||||
No specialized flows configured.
|
||||
</skills>
|
||||
|
||||
<acceptance_criteria>
|
||||
|
||||
## AC-1: Personalizacja zapisana w bazie danych
|
||||
```gherkin
|
||||
Given zamówienie z shopPRO zawiera produkty z custom_fields
|
||||
When import zamówienia się wykonuje (cron lub ręczny)
|
||||
Then kolumna personalization w order_items zawiera dane personalizacji jako czysty tekst (bez HTML)
|
||||
```
|
||||
|
||||
## AC-2: Personalizacja wyświetlana w szczegółach zamówienia
|
||||
```gherkin
|
||||
Given zamówienie w orderPRO ma pozycje z wypełnioną personalizacją
|
||||
When użytkownik otwiera szczegóły zamówienia (/orders/{id})
|
||||
Then pod nazwą produktu wyświetla się sekcja personalizacji z etykietami i wartościami
|
||||
```
|
||||
|
||||
## AC-3: Brak personalizacji nie powoduje błędów
|
||||
```gherkin
|
||||
Given zamówienie z shopPRO zawiera produkty BEZ custom_fields (puste lub null)
|
||||
When import się wykonuje i użytkownik otwiera szczegóły
|
||||
Then kolumna personalization jest NULL i w UI nie pojawia się sekcja personalizacji
|
||||
```
|
||||
|
||||
</acceptance_criteria>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Migracja DB + mapping personalizacji</name>
|
||||
<files>database/migrations/20260401_000063_add_personalization_to_order_items.sql, src/Modules/Settings/ShopproOrderMapper.php, src/Modules/Orders/OrderImportRepository.php</files>
|
||||
<action>
|
||||
1. Utworzyć migrację dodającą kolumnę `personalization TEXT NULL` do tabeli `order_items` (po kolumnie `payload_json`).
|
||||
|
||||
2. W `ShopproOrderMapper::mapItems()` (linia 561-580):
|
||||
- Wyciągnąć `custom_fields` z `$row` za pomocą `$this->readPath($row, ['custom_fields'])`
|
||||
- Przekonwertować HTML na czysty tekst: zamienić `<br>` na `\n`, usunąć tagi HTML (`strip_tags`), `html_entity_decode`, `trim`
|
||||
- Zapisać jako klucz `personalization` w tablicy wynikowej (obok `payload_json`)
|
||||
- Jeśli wynik jest pustym stringiem, ustawić `null`
|
||||
|
||||
3. W `OrderImportRepository::replaceItems()`:
|
||||
- Dodać kolumnę `personalization` do INSERT query
|
||||
- Bindować wartość z tablicy item
|
||||
|
||||
Avoid: Nie zmieniać formatu `payload_json` — surowe dane API muszą zostać nienaruszone.
|
||||
Avoid: Nie parsować HTML do JSON — czysty tekst z zachowanymi newlines jest wystarczający.
|
||||
</action>
|
||||
<verify>
|
||||
- Migracja wykonuje się bez błędów: `php database/migrate.php`
|
||||
- Po re-imporcie zamówienia z shopPRO kolumna `personalization` zawiera tekst
|
||||
- Zamówienia bez personalizacji mają NULL w kolumnie
|
||||
</verify>
|
||||
<done>AC-1 i AC-3 satisfied: personalizacja zapisywana w DB, brak personalizacji = NULL</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Wyświetlanie personalizacji w widoku zamówienia</name>
|
||||
<files>resources/views/orders/show.php, resources/scss/orders/_show.scss</files>
|
||||
<action>
|
||||
1. W `resources/views/orders/show.php`, w sekcji renderującej produkty zamówienia:
|
||||
- Pod nazwą produktu (`original_name`) dodać blok warunkowy: jeśli `$item['personalization']` nie jest puste
|
||||
- Wyświetlić personalizację w `<div class="item-personalization">` z ikoną lub etykietą "Personalizacja:"
|
||||
- Każda linia personalizacji (split po `\n`) jako osobna linia w UI
|
||||
- Escape HTML: użyć `e()` helpera na każdej linii
|
||||
|
||||
2. W SCSS dodać style:
|
||||
- `.item-personalization` — mały font (0.85em), kolor muted, lekki padding-top
|
||||
- Etykiety (tekst przed `:`) mogą być pogrubione via CSS lub pozostawione jako plain text
|
||||
- Kompaktowy układ, bez nadmiernych marginesów
|
||||
|
||||
Avoid: Nie renderować surowego HTML z custom_fields — zawsze escape.
|
||||
Avoid: Nie dodawać nowych zależności JS — to statyczny tekst.
|
||||
</action>
|
||||
<verify>
|
||||
- Otworzyć zamówienie z personalizacją w przeglądarce — personalizacja widoczna pod nazwą produktu
|
||||
- Otworzyć zamówienie bez personalizacji — brak dodatkowej sekcji
|
||||
- Sprawdzić XSS: wpisać `<script>alert(1)</script>` w custom_fields shopPRO — powinno być escaped
|
||||
</verify>
|
||||
<done>AC-2 satisfied: personalizacja wyświetlana w UI pod nazwą produktu</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<boundaries>
|
||||
|
||||
## DO NOT CHANGE
|
||||
- shopPRO codebase (API już zwraca custom_fields — zero zmian po stronie shopPRO)
|
||||
- payload_json format i zawartość w order_items
|
||||
- Istniejące kolumny i indeksy order_items
|
||||
- Logika importu zamówień poza mapowaniem items (OrderImportRepository::upsertOrderAggregate flow)
|
||||
|
||||
## SCOPE LIMITS
|
||||
- Tylko personalizacja z shopPRO (nie Allegro, nie Erli)
|
||||
- Tylko widok szczegółów zamówienia — bez zmian na liście zamówień
|
||||
- Bez edycji personalizacji w orderPRO — read-only display
|
||||
- Bez parsowania personalizacji do struktury klucz-wartość (JSON) — plain text wystarczy
|
||||
|
||||
</boundaries>
|
||||
|
||||
<verification>
|
||||
Before declaring plan complete:
|
||||
- [ ] Migracja wykonuje się bez błędów
|
||||
- [ ] SCSS kompiluje się bez błędów
|
||||
- [ ] Zamówienie z personalizacją — dane widoczne w UI
|
||||
- [ ] Zamówienie bez personalizacji — brak sekcji w UI
|
||||
- [ ] Brak regresji w istniejącym wyświetlaniu produktów
|
||||
- [ ] XSS escape działa poprawnie
|
||||
- [ ] Aktualizacja DOCS/DB_SCHEMA.md i DOCS/ARCHITECTURE.md
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Wszystkie taski zakończone
|
||||
- Wszystkie weryfikacje przechodzą
|
||||
- Brak błędów PHP/SCSS
|
||||
- Personalizacja widoczna w UI dla produktów z custom_fields
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.paul/phases/63-order-item-personalization/63-01-SUMMARY.md`
|
||||
</output>
|
||||
127
.paul/phases/63-order-item-personalization/63-01-SUMMARY.md
Normal file
127
.paul/phases/63-order-item-personalization/63-01-SUMMARY.md
Normal file
@@ -0,0 +1,127 @@
|
||||
---
|
||||
phase: 63-order-item-personalization
|
||||
plan: 01
|
||||
subsystem: orders
|
||||
tags: [personalization, shopPRO, import, custom_fields]
|
||||
|
||||
requires:
|
||||
- phase: none
|
||||
provides: n/a
|
||||
provides:
|
||||
- Kolumna personalization w order_items
|
||||
- Ekstrakcja custom_fields z shopPRO API przy imporcie
|
||||
- Wyswietlanie personalizacji w widoku zamowienia
|
||||
affects: []
|
||||
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns: [extractPersonalization HTML-to-text w mapperze]
|
||||
|
||||
key-files:
|
||||
created:
|
||||
- database/migrations/20260401_000075_add_personalization_to_order_items.sql
|
||||
modified:
|
||||
- src/Modules/Settings/ShopproOrderMapper.php
|
||||
- src/Modules/Orders/OrderImportRepository.php
|
||||
- resources/views/orders/show.php
|
||||
- resources/scss/app.scss
|
||||
- public/assets/css/app.css
|
||||
|
||||
key-decisions:
|
||||
- "Personalizacja jako plain text (nie JSON) — prostosc, wystarczajaca dla wyswietlania"
|
||||
- "date_order dodane do readPath mapper — naprawa brakujacej daty zamowienia"
|
||||
|
||||
patterns-established:
|
||||
- "extractPersonalization: HTML strip + br-to-newline dla danych z shopPRO"
|
||||
|
||||
duration: ~45min
|
||||
started: 2026-04-01T19:00:00Z
|
||||
completed: 2026-04-01T19:45:00Z
|
||||
---
|
||||
|
||||
# Phase 63 Plan 01: Order Item Personalization Summary
|
||||
|
||||
**Import i wyswietlanie danych personalizacji produktow z shopPRO (custom_fields) w szczegolach zamowienia orderPRO.**
|
||||
|
||||
## Performance
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Duration | ~45min |
|
||||
| Started | 2026-04-01 |
|
||||
| Completed | 2026-04-01 |
|
||||
| Tasks | 2 completed |
|
||||
| Files modified | 7 |
|
||||
|
||||
## Acceptance Criteria Results
|
||||
|
||||
| Criterion | Status | Notes |
|
||||
|-----------|--------|-------|
|
||||
| AC-1: Personalizacja zapisana w DB | Pass | custom_fields ekstrakcja z HTML na tekst, zapis w kolumnie personalization |
|
||||
| AC-2: Personalizacja wyswietlana w UI | Pass | Blok pod nazwa produktu z etykieta i liniami tekstu |
|
||||
| AC-3: Brak personalizacji nie powoduje bledow | Pass | NULL w kolumnie, brak sekcji w UI |
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- Kolumna `personalization TEXT NULL` w `order_items` + ekstrakcja `custom_fields` z shopPRO API
|
||||
- Wyswietlanie personalizacji w widoku zamowienia z escape XSS
|
||||
- Naprawa brakujacej daty zamowienia (`date_order` dodane do mapper readPath)
|
||||
- Usuniecie zbednego pola `item_type` z widoku i duplikatu `source_order_id`
|
||||
- Dodanie `margin-bottom` do section-title dla lepszego odstepy pod kreska
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
| File | Change | Purpose |
|
||||
|------|--------|---------|
|
||||
| `database/migrations/20260401_000075_add_personalization_to_order_items.sql` | Created | Kolumna personalization w order_items |
|
||||
| `src/Modules/Settings/ShopproOrderMapper.php` | Modified | extractPersonalization() + date_order w readPath |
|
||||
| `src/Modules/Orders/OrderImportRepository.php` | Modified | personalization w INSERT query |
|
||||
| `resources/views/orders/show.php` | Modified | Wyswietlanie personalizacji, usuniecie item_type i source_order_id |
|
||||
| `resources/scss/app.scss` | Modified | Style .item-personalization + section-title margin-bottom |
|
||||
| `public/assets/css/app.css` | Modified | Skompilowany CSS |
|
||||
| `DOCS/DB_SCHEMA.md` | Modified | Dokumentacja kolumny personalization |
|
||||
| `DOCS/TECH_CHANGELOG.md` | Modified | Wpis Phase 63 |
|
||||
|
||||
## Decisions Made
|
||||
|
||||
| Decision | Rationale | Impact |
|
||||
|----------|-----------|--------|
|
||||
| Plain text zamiast JSON dla personalizacji | Prostosc — dane sa read-only, nie wymagaja struktury klucz-wartosc | Wystarczajace dla wyswietlania |
|
||||
| date_order w readPath mappera | shopPRO API zwraca date_order, mapper nie mial tego klucza | Naprawia brakujaca date zamowienia |
|
||||
| Usuniecie item_type z widoku | Zawsze "product", zero informacji | Czystszy UI |
|
||||
| Usuniecie source_order_id z widoku | Duplikat external_order_id | Czystszy UI |
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Summary
|
||||
|
||||
| Type | Count | Impact |
|
||||
|------|-------|--------|
|
||||
| Scope additions | 3 | Drobne poprawki UI wykryte przy testowaniu |
|
||||
| Deferred | 0 | - |
|
||||
|
||||
**Total impact:** Drobne poprawki UI (date_order mapping, item_type/source_order_id cleanup, section-title spacing) — naturalne odkrycia przy testowaniu na zywo.
|
||||
|
||||
## Issues Encountered
|
||||
|
||||
| Issue | Resolution |
|
||||
|-------|------------|
|
||||
| Lokalna DB offline | Migracja uruchomiona na zdalnej DB przez mysql CLI |
|
||||
| Cron nie pobral zamowienia (stary updated_at) | Touch updated_at w shopPRO DB + reset kursora sync |
|
||||
| marianek.pl to osobna instancja shopPRO | Znaleziony config.php z danymi DB |
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
**Ready:**
|
||||
- Personalizacja importowana i wyswietlana
|
||||
- Mapper rozszerzalny o kolejne pola shopPRO API
|
||||
|
||||
**Concerns:**
|
||||
- Brak
|
||||
|
||||
**Blockers:**
|
||||
- None
|
||||
|
||||
---
|
||||
*Phase: 63-order-item-personalization, Plan: 01*
|
||||
*Completed: 2026-04-01*
|
||||
Reference in New Issue
Block a user