Commit Graph

251 Commits

Author SHA1 Message Date
dd5c4d1708 fix(shipments): wybor przewoznika Allegro dla uslug WZA z carrierId=INPOST
Widoki settings/allegro i shipments/prepare wymuszaly carrier=InPost na
podstawie stripos(provider_carrier_id, 'inpost'), choc realny provider
to allegro_wza. Allegro WZA zwraca carrierId='INPOST' dla Paczkomatow
InPost — to opis kuriera za usluga, a nie wybor providera w UI.

Po fixie auto-wybor i render mapowania opieraja sie wylacznie na polu
provider z carrier_delivery_method_mappings. Zapis DB byl od poczatku
poprawny.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 11:19:43 +02:00
67e525529e refactor(automation): rozbij AutomationController na slim + 3 wspolpracownikow
AutomationController.php 677 -> 221 lin. (67% redukcji). Wydzielono:
- AutomationRequestParser (422) - stale ALLOWED_*/PAYMENT_*, walidacja,
  ekstrakcja conditions/actions/ruleData, buildRule.
- AutomationFormViewModel (80) - przygotowanie zmiennych template'a
  automation/form (przejal ReceiptConfigRepository).
- AutomationHistoryFilters (58) - filtry historii + aktywna zakladka.

Szablon destroy/duplicate/toggleStatus zlozony do runIdAction().
Zero zmian kontraktu HTTP/widokow/DB.

Plan: .paul/plans/20260520-1400-refactor-automation-controller/

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 10:58:52 +02:00
2c1ad4a262 fix(auth): naprawa strony /login (subtitle, inline remember, auto-login z cookie)
- usuniety subtitle "Zaloguj sie, aby przejsc..." z widoku
- "Zapamietaj mnie (30 dni)" w jednej linii (selektor .form-field.remember-field)
- AuthController::showLogin woluje loginFromRememberToken() -> uzytkownik z waznym
  cookie remember (30 dni) jest auto-logowany po wygasnieciu sesji PHP zamiast
  ogladac formularz logowania

PLAN: .paul/plans/20260520-1200-fix-login-page-and-remember-me/

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 08:33:59 +02:00
561e39f775 update 2026-05-19 23:46:57 +02:00
7ca6f4e462 refactor(shipments): rozbij DeliveryStatus na fasade + 3 wspolpracownikow
DeliveryStatus (657 lin.) byl god-klasa statusow uzywana globalnie
(56 wywolan w 20 plikach). ~400 linii to tablice const map dostawcow.

Wydzielono zachowujac 100% kontraktu publicznego (fasada deleguje):
- DeliveryStatusProviderMap  - mapy surowych statusow + normalize/description/getDefaultMappings/overrides
- AllegroDescriptionGuesser  - slugify + guessStatusFromDescription + wzorce
- DeliveryTrackingUrlBuilder - trackingUrl + URL kurierow/dostawcow

DeliveryStatus.php 657 -> 170 lin. Zero zmian w plikach konsumentow.
tests/Unit/DeliveryStatusTest.php przechodzi bez modyfikacji (4/4).

Plan/SUMMARY: .paul/plans/20260519-1730-refactor-delivery-status/

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 23:46:17 +02:00
e12ebe3a6f update 2026-05-19 23:23:18 +02:00
38093404e2 update 2026-05-19 21:28:27 +02:00
e77b0f12a2 refactor(routing): module providers + lazy ServiceRegistry
Rozbicie routes/web.php (859 lin.) na 24 klasy <Modul>Module.php zgodnie
z quality_risks.md priorytet #4. Kontroler buduje sie tylko gdy router
trafi w jego route (lazy closure factory + memoizacja per request).

- src/Core/Routing/ServiceRegistry.php (~55 lin.) + ModuleProvider interface
- 24 module providers w src/Modules/*/Module.php
- routes/web.php: 859 -> 78 lin. (orkiestrator)
- 7 testow ServiceRegistry pass, zero regresji w istniejacych testach
- 191 route'ow zachowanych 1:1 (diff baseline vs after pusty)
- DeliveryStatus::setRepository przeniesione do ShipmentsModule

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 21:25:07 +02:00
2df4638365 update 2026-05-19 20:50:31 +02:00
cff0635aff UPDATE 2026-05-19 00:40:34 +02:00
9ea26ad610 update 2026-05-18 20:12:00 +02:00
d30a459b1e fix(145): correct polkurier cod return codes
Phase 145 complete:

- send COD.codtype=S for standard Polkurier COD return time

- send COD.return_cod=BA for bank-account transfer

- add regression coverage and PAUL documentation
2026-05-18 15:22:12 +02:00
ea039c6e8c 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>
2026-05-18 12:42:11 +02:00
d23dec8704 fix(143): polish orders list and sidebar first paint
Phase 143 complete:

- remove orders list intro card

- apply persisted collapsed sidebar state before CSS first paint

- update PAUL and technical docs
2026-05-18 11:52:20 +02:00
2f89901ebf fix(142): preselect polkurier shipment mapping
Phase 142 complete:

- preselect Polkurier carrier and service in shipment prepare

- add render regression test for Polkurier mapping

- document hotfix and verification gaps
2026-05-18 10:36:24 +02:00
ca0b37a86f feat(141): group integrations hub sections 2026-05-18 10:25:18 +02:00
7fd88038e4 feat(140): shoppro polkurier delivery mapping
Phase 140 complete:

- add Polkurier as shopPRO delivery mapping provider

- reuse PolkurierShipmentService delivery services

- update PAUL state, docs, and changelog
2026-05-18 10:00:26 +02:00
06fd41a61d update 2026-05-17 23:37:51 +02:00
251025fffc feat(139): sonar critical major cleanup
Phase 139 complete:

- 139-01 refreshed Sonar baseline and cleaned delivery-status/statistics slice

- 139-02 reduced BLOCKER/CRITICAL/MAJOR issues from 605 to 495

- Added typed exceptions and migrated alert includes to component helper
2026-05-17 23:31:23 +02:00
ff91a29e4f update 2026-05-17 20:54:50 +02:00
9f2b5e5f3b feat(138): security and legacy hardening
Phase 138 complete:

- Harden SMTP mailbox TLS verification with local/dev override

- Block unknown email/SMS template variables through shared catalog

- Centralize session access and replace targeted view require/FQCN patterns

Verification:

- php -l on touched files

- rg checks for raw session, targeted require, and inline App references

- git diff --check

- PHPUnit and Sonar gaps documented because local tools are unavailable
2026-05-17 18:39:17 +02:00
bdf415501f feat(136): fakturownia invoice idempotency
Phase 136 complete:

- add local pending/failed external invoice attempt state

- reconcile delegated invoices by stable Fakturownia oid before duplicate POST

- document INVOICE-IDEMP-115 resolution and verification gaps
2026-05-17 17:40:12 +02:00
d3b4d378f7 update 2026-05-16 21:55:33 +02:00
af03d6a3ce feat(135): accounting net correctness
Phase 135 complete:

- Store VAT-aware total_net for new receipts

- Use source net or item-level VAT fallback for daily statistics

- Document no-backfill boundary and tooling gaps
2026-05-16 21:54:09 +02:00
53f01c392c feat(134): backlog reality check
Phase 134 complete:

- audit todo.md and concerns.md against current code/docs

- classify active, implemented, stale and decision-dependent backlog items

- route confirmed work to phases 135-142

Verification:

- git diff --check

- no runtime files changed

- sonar-scanner gap documented
2026-05-16 20:43:31 +02:00
0c1246b522 feat(133): erli cross-surface parity
Phase 133 complete:

- Add shared order source registry for Allegro, shopPRO, and Erli

- Include Erli in order filters, statistics, automation integration filters, and integration menu state

- Document verification gaps for missing PHPUnit vendor and sonar-scanner
2026-05-16 16:26:14 +02:00
8f4745400e feat(132): erli hardening observability docs
Phase 132 complete:

- unify Erli inbox import diagnostics and ACK failure handling

- add unit coverage for ACK safety and status push diagnostics

- document Erli observability without schema changes

Co-Authored-By: OpenAI Codex <noreply@openai.com>
2026-05-16 15:53:43 +02:00
f9792a4a3f feat(131): erli tracking automation hooks
Phase 131 complete:

- retry Erli external parcel sync from shipment tracking cron

- keep local provider tracking as source of truth, Allegro-style

- extend shared shipment automation context and tests

Co-Authored-By: OpenAI Codex <noreply@openai.com>
2026-05-16 15:37:07 +02:00
380146bf07 Merge branch 'main' of https://git.project-pro.pl/Project-Pro/orderPRO
# Conflicts:
#	.paul/PROJECT.md
#	.paul/ROADMAP.md
#	.paul/STATE.md
#	.paul/codebase/tech_changelog.md
#	resources/lang/pl.php
#	resources/views/shipments/prepare.php
#	routes/web.php
#	src/Modules/Settings/IntegrationsHubController.php
#	src/Modules/Shipments/ShipmentController.php
2026-05-16 01:04:56 +02:00
ea73769bd3 chore(paul): record phase 130 closure 2026-05-16 00:58:32 +02:00
13f570e5af feat(130): erli shipments and labels 2026-05-16 00:58:21 +02:00
4258751e80 chore(paul): record phase 129 commit 2026-05-16 00:27:43 +02:00
7972bb9fa4 feat(129): erli status mapping sync
Phase 129 complete:
- Add Erli pull/push status mapping tables, seeds and repositories
- Wire Erli status sync cron for inbox pull and manual-only push
- Add tabbed Erli settings UI, tests and documentation

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-16 00:27:28 +02:00
c127ebf04d chore(paul): record phase 128 transition 2026-05-15 23:54:36 +02:00
2565d9b754 feat(128): erli orders import
Phase 128 complete:
- add Erli /inbox order import with safe mark-read ACK
- add cron/manual import controls and sync state tracking
- map Erli orders into orderPRO aggregates with mapper tests and docs
2026-05-15 23:54:22 +02:00
3ea8cdc941 chore(paul): record phase 127 transition 2026-05-15 23:26:57 +02:00
d6b18a6438 feat(127): erli integration foundation
Phase 127 complete:

- add global Erli settings schema and encrypted API key repository

- add real read-only Erli API connection test and settings UI

- expose Erli in integrations hub and update PAUL/docs state
2026-05-15 23:26:44 +02:00
f4bd9dee30 update 2026-05-15 20:33:04 +02:00
6ae91a3fbe update 2026-05-14 17:18:29 +02:00
27df08e661 feat(130): polkurier delivery status mappings UI
Phase 130 complete (1 plan):
- POLKURIER_MAP + POLKURIER_DESCRIPTIONS w DeliveryStatus.php (7 wpisow O/P/A/WP/D/Z/W z dokumentacji v1.11)
- 'polkurier' w PROVIDERS w DeliveryStatusesController + DeliveryStatusMappingController
- countAllUnmappedForBadge() zlicza polkurier
- Defaulty hardcoded w kodzie (spojnie z InPost/Apaczka/Allegro); migracja Phase 128 staje sie no-op
- Zero zmian w widoku (_delivery-status-mappings-content.php auto-iteruje po providerach)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 17:17:48 +02:00
48351b5f36 feat(129): order user notes module
CRUD notatek autorskich operatora per zamowienie z badge [N] na liscie
zamowien. Reuse istniejacej tabeli `order_notes` przez nowy
`note_type='user'` z `user_id` (FK->users SET NULL) i `author_name`
(snapshot). Sekcja `#notes` w "Wiadomosci i zalaczniki" w
`/orders/{id}` z inline edit form + delete przez
`OrderProAlerts.confirm`. Autoryzacja DB-level
(`WHERE user_id = :user_id`, rowCount=0 ⇒ 403) — bez admin override
(brak systemu rol w aplikacji).

- Migracja `20260514_000116_*.sql` (ADD COLUMN user_id + author_name +
  FK + indeks `idx_order_notes_type_order`); idempotentne z DDL
  no-op fallback.
- `OrderNotesService` (CRUD + walidacja body ≤ 2000 znakow); subquery
  `user_notes_count` w paginate; badge HTML w `toTableRow()`.
- 3 routy POST /orders/{id}/notes(/update|/delete).
- SCSS module `_order-notes.scss` + vanilla JS `order-notes.js`
  (inline edit toggle + delete confirm; idempotent guard).
- 9 kluczy i18n PL; PROJECT.md + ROADMAP.md + tech_changelog.md +
  db_schema.md zaktualizowane.

Follow-up: `php bin/migrate.php` + manualny smoke test (autor vs inny
user + badge na /orders/list).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 15:20:05 +02:00
c78ac335ee feat(128): polkurier shipment service + tracking + UI prepare
PolkurierApiClient rozszerzony do pelnego kontraktu (7 metod):
createShipment/getLabel/getStatus/cancelOrder/getAvailableCarriers/
getInpostParcelMachines/getCourierPoints. Wspolny call() parsuje
envelope {status, response}. Kontrakt zweryfikowany na oficjalnej
dokumentacji PDF v1.11.

PolkurierShipmentService (implements ShipmentProviderInterface)
orchestruje pelen flow: normalizeShipmentType (lowercase), split
ulicy, build recipient/sender/pickup, COD z bank account z
company_settings, extractOrderNumber/extractTrackingNumber
priorytetujace SDK Order entity (number, waybills[0].number).

PolkurierTrackingService (implements ShipmentTrackingInterface)
mapuje statusy O/P/A/WP/D/Z/W przez delivery_status_mappings.

UI panel polkurier w prepare.php z dynamiczna lista uslug z
available_carriers. Bez dedykowanego selektora punktu — operator
wpisuje receiver_point_id w istniejace pole w sekcji Adres odbiorcy.

Migracja 20260514_000115 seedujaca 7 wpisow delivery_status_mappings
z oficjalnej tabeli ORDER_STATUS (O/P/A/WP/D/Z/W).

Live test #114/#115 zakonczony sukcesem po 4 iteracjach
(ReferenceError -> uppercase shipmenttype -> orderno parsing ->
A4/A6 etykieta). Rozmiar etykiety A4/A6 sterowany w panelu klienta
polkurier.pl, NIE przez API.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 12:56:36 +02:00
3443879f59 feat(127): polkurier integration foundation
Single-instance globalna konfiguracja polkurier.pl jako alternatywa
dla Apaczki: szyfrowany login + Token API, karta w hubie integracji
i realny test polaczenia przez apimetod=test_auth_api zweryfikowany
na zywym koncie operatora (Autoryzacja: 1).

ShipmentProviderRegistry netkniety - PolkurierShipmentService/
TrackingService w kolejnych fazach.

Kluczowe ustalenia kontraktu API (z SDK polkurier-sdk):
- POST https://api.polkurier.pl/ (jeden endpoint)
- JSON body: {authorization:{login,token}, apimetod, data}
- Sukces: top-level status === 'success' (nie 'ok')
- Blad: tresc w polu 'response' envelope'a
- Content-Type: application/json (strict, bez charset suffix)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 11:43:11 +02:00
541e61bf7d update 2026-05-13 17:38:57 +02:00
afdbc67887 upadte 2026-05-12 22:36:08 +02:00
c758ec7c92 feat(126): invoice GUS field mapping fix (JDG/KRS heuristic)
MfWhitelistApiClient.lookupByNip() exposes is_jdg/krs from MF Biala Lista.
InvoiceController.nipLookup propagates is_jdg in JSON response.
invoice_form.php JS conditionally targets buyer_name (JDG) or
buyer_company_name (spolka z KRS); second field keeps zamowienie pre-fill.

Fixes apparent field swap on /orders/{id}/invoice/create after GUS lookup
for JDG (sole trader) where MF returns natural person in subject.name.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 22:29:55 +02:00
2ab461aaae feat(125): invoice_requested import fix + drop legacy is_invoice column
- shopPRO: ShopproOrderMapper jako jedyne zrodlo heurystyki detekcji faktury;
  mapOrderAggregate() zwraca top-level invoice_detected (transient).
- ShopproOrdersSyncService: usunieta wlasna shouldRequestInvoice(); propagacja
  aggregate['invoice_detected'] do setInvoiceRequested() tylko przy created=true.
- Allegro: nowa shouldRequestInvoice(payload) z 4 wzorcami (invoice.required,
  naturalPerson=false, address.taxId, companyName/address.company.name).
  Wczesniej tylko invoice.required -> analogiczna luka jak shopPRO.
- Migracja 20260513_000113: idempotentny backfill (UPDATE invoice_requested=1
  WHERE is_invoice=1 AND invoice_requested=0) + DROP COLUMN orders.is_invoice.
  Guard przez information_schema.COLUMNS + PREPARE/EXECUTE z ALTER TABLE COMMENT
  no-op fallbackiem (portable MySQL/MariaDB).
- Cleanup is_invoice z OrderImportRepository (INSERT cols/values/params,
  docstring Phase 112) i OrdersRepository (paginate SELECT, transformOrderRow
  hydrate). AllegroOrderImportService mapping w mapCheckoutFormPayload tez
  usuniety (wymuszone konsekwencja DROP COLUMN).
- Bugfix #1089: zamowienie shopPRO z firm_nip (bez wants_invoice/invoice.required)
  ustawia teraz invoice_requested=1 -> UI w zakladce Platnosci zaznacza checkbox,
  przycisk "Wystaw fakture" widoczny.

Pending operator: php bin/migrate.php (XAMPP MySQL online) -> backfill 7 zamowien.
Smoke test: re-import shopPRO + nowe Allegro z NIP.
2026-05-12 22:11:49 +02:00
e7a417bc22 update 2026-05-12 21:37:58 +02:00
522c94a434 feat(124): sms templates CRUD + order picker
- Nowa tabela sms_templates (name + body + is_active) + minimalny CRUD.
- /settings/sms-templates: lista + formularz z paleta zmiennych (pill chips).
- Wydzielono Sms\SmsVariableResolver ze wspolna logika placeholderow;
  Email\VariableResolver staje sie cienka fasada — EmailSendingService bez zmian.
- Dropdown "Wybierz szablon" w zakladce SMS na /orders/{id} z fetch
  GET /orders/{id}/sms/template + OrderProAlerts.confirm przy nadpisaniu.
- Stopka SMSPLANET dalej doklejana wylacznie przez SmsConversationService
  (Phase 122 contract preserved).
- Sidebar Ustawien: nowy link "Szablony SMS".

Migration: 20260512_000112_create_sms_templates.sql (CREATE TABLE).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 21:37:51 +02:00
0227f2d072 feat(123): receipts export xlsx VAT breakdown
- AccountingController::export(): new headers (Numer | Data wystawienia | Kwota brutto | Kwota netto | Stawka VAT | Kwota VAT), removed Data sprzedazy/Konfiguracja/Nr zamowienia/Nr referencyjny
- buildVatBreakdown() helper groups items_json by vat rate, emits one XLSX row per (receipt x rate); legacy receipts (no `vat` in snapshot) fallback to net=brutto/1.23
- ReceiptService::buildItemsSnapshot(): writes `vat` per item from order_items.tax_rate (fallback 23.0); shipping cost item gets vat=23.0
- RECEIPT-NET-FIX deferred (.paul/codebase/todo.md): ReceiptService::issue() still saves total_net=total_gross

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 21:06:53 +02:00