---
phase: 121-smsplanet-conversation-notifications
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
  - database/migrations/20260512_000110_smsplanet_conversation_notifications.sql
  - src/Modules/Settings/SmsplanetIntegrationRepository.php
  - src/Modules/Settings/SmsplanetIntegrationController.php
  - src/Modules/Settings/SmsplanetApiClient.php
  - src/Modules/Sms/SmsMessageRepository.php
  - src/Modules/Sms/SmsConversationService.php
  - src/Modules/Sms/SmsplanetWebhookController.php
  - src/Modules/Notifications/NotificationRepository.php
  - src/Modules/Notifications/NotificationController.php
  - src/Modules/Notifications/NotificationApiController.php
  - src/Modules/Orders/OrdersController.php
  - routes/web.php
  - resources/views/settings/smsplanet.php
  - resources/views/orders/show.php
  - resources/views/notifications/index.php
  - resources/views/layouts/app.php
  - resources/lang/pl.php
  - resources/scss/app.scss
  - public/assets/css/app.css
  - public/assets/js/modules/notifications.js
  - DOCS/DB_SCHEMA.md
  - DOCS/ARCHITECTURE.md
  - DOCS/TECH_CHANGELOG.md
autonomous: true
delegation: auto
---

<objective>
## Goal
Wdrozyc dwukierunkowa komunikacje SMSPLANET w orderPRO: konfiguracje wysylki z nadpisu albo numeru 2WAY, odbior webhookow przychodzacych SMS, historie rozmowy SMS w zamowieniu oraz globalne centrum powiadomien z pollingiem i powiadomieniami przegladarki.

## Purpose
Operator ma prowadzic rozmowe SMS z klientem bez opuszczania szczegolow zamowienia, a nowe odpowiedzi klientow maja byc widoczne globalnie jako notyfikacje.

## Output
Nowa migracja DB, backend SMS/notifications, publiczny webhook SMSPLANET, nowa zakladka SMS w zamowieniu, topbar z licznikiem notyfikacji, podstrona historii notyfikacji oraz dokumentacja techniczna.
</objective>

<context>
<clarifications>
- **Dopasowanie** - Przy wiadomosci przychodzacej z SMSPLANET dopasowujemy ja do najnowszego zamowienia po numerze telefonu klienta, czy wymagamy kodu zamowienia?
  -> Odpowiedz: Do ostatniego zamowienia.
- **Widocznosc** - Historia SMS ma byc nowa zakladka w szczegolach zamowienia czy czesc obecnej zakladki Historia?
  -> Odpowiedz: Nowa zakladka.
- **Polling** - Czy powiadomienia moga dzialac przez polling, czy wymagany jest realtime transport?
  -> Odpowiedz: Moze byc polling.
- **Webhook** - Czy wdrazamy weryfikacje podpisu SMSPLANET Signature od razu?
  -> Odpowiedz: Na razie bez podpisu.
</clarifications>

## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
@.paul/STATE.md
@.paul/codebase/architecture.md
@.paul/codebase/db_schema.md
@AGENTS.md
@DOCS/ARCHITECTURE.md
@DOCS/DB_SCHEMA.md

## Source Files
@database/migrations/20260512_000108_create_smsplanet_integration_settings.sql
@src/Modules/Settings/SmsplanetApiClient.php
@src/Modules/Settings/SmsplanetIntegrationRepository.php
@src/Modules/Settings/SmsplanetIntegrationController.php
@src/Modules/Orders/OrdersController.php
@src/Modules/Orders/OrdersRepository.php
@resources/views/settings/smsplanet.php
@resources/views/orders/show.php
@resources/views/layouts/app.php
@resources/lang/pl.php
@routes/web.php
</context>

<skills>
## Required Skills (from SPECIAL-FLOWS.md)

| Skill | Priority | When to Invoke | Loaded? |
|-------|----------|----------------|---------|
| sonar-scanner CLI | required | After APPLY, before UNIFY | not loaded |

## Skill Invocation Checklist
- [ ] Run `sonar-scanner` after implementation, then record any new issues in `DOCS/todo.md` according to `.paul/SPECIAL-FLOWS.md`.
</skills>

<acceptance_criteria>

## AC-1: SMSPLANET Sender Mode
```gherkin
Given SMSPLANET integration settings are opened
When operator selects sender mode "nadpis" or "numer 2WAY" and saves settings
Then orderPRO stores the selected mode, preserves the configured text sender and stores the 2WAY phone number separately
```

## AC-2: Outgoing SMS Uses Selected Sender
```gherkin
Given SMSPLANET is active and complete
When operator sends a test SMS or sends SMS from an order conversation
Then API payload uses `from` from the selected sender mode and no hardcoded test override remains
```

## AC-3: Incoming SMS Webhook
```gherkin
Given SMSPLANET posts an incoming SMS webhook without signature
When orderPRO receives sender phone, recipient phone and message body
Then it stores the inbound message, matches it to the latest order with that customer phone, and returns a 2xx response
```

## AC-4: Order SMS Conversation
```gherkin
Given an order has inbound or outbound SMS messages
When operator opens the order detail page
Then a separate SMS tab shows the chronological conversation and lets the operator send another SMS to the customer
```

## AC-5: Notification Center
```gherkin
Given an inbound SMS is received
When operator is logged in
Then the topbar notification icon shows an unread count, the notification center lists the event, and the notification links to the matched order SMS tab
```

## AC-6: Browser Notifications
```gherkin
Given browser notifications are allowed
When notification polling detects a new unread inbound SMS notification
Then the browser displays a native notification with concise SMS context and clicking it opens the target order
```

</acceptance_criteria>

<tasks>

<task type="auto">
  <name>Task 1: Add SMS and notification persistence plus backend services</name>
  <files>database/migrations/20260512_000110_smsplanet_conversation_notifications.sql, src/Modules/Settings/SmsplanetIntegrationRepository.php, src/Modules/Settings/SmsplanetApiClient.php, src/Modules/Sms/SmsMessageRepository.php, src/Modules/Sms/SmsConversationService.php, src/Modules/Sms/SmsplanetWebhookController.php, src/Modules/Notifications/NotificationRepository.php, routes/web.php, DOCS/DB_SCHEMA.md, DOCS/ARCHITECTURE.md, DOCS/TECH_CHANGELOG.md</files>
  <action>
    Create schema and backend foundation:
    - Alter `smsplanet_integration_settings` with `sender_mode` (`text`/`phone`) and `sender_phone`; keep existing `sender` as text sender/nadpis.
    - Create `sms_messages` with direction (`inbound`/`outbound`), provider (`smsplanet`), nullable `order_id`, `from_phone`, `to_phone`, `body`, `message_id`, `status`, `raw_payload_json`, `created_by`, timestamps and indexes for `(order_id, created_at)`, normalized phone matching, and provider message id.
    - Create `notifications` with type, title, body, target_url, related_order_id, related_sms_message_id, read_at, created_at and indexes for unread polling.
    - Implement SMS repository/service methods for sending outbound SMS, storing outbound result, storing inbound webhook payload, normalizing PL/international phone variants, and matching inbound SMS to the latest order whose customer/delivery/invoice phone matches.
    - Implement notification repository create/list/unread/mark-read methods.
    - Add public POST webhook route `/webhooks/smsplanet/inbound` without auth middleware and without CSRF; no signature verification in this plan, but store raw payload and isolate parsing in a method so signature validation can be added later.
    - Use PDO prepared statements only; do not concatenate user values into SQL.
    - Remove the temporary `TEST_SENDER_OVERRIDE` from `SmsplanetIntegrationController`.
  </action>
  <verify>`C:\xampp\php\php.exe -l` on all new/changed PHP files; inspect migration for valid MySQL syntax; manually POST a sample webhook and confirm 2xx plus inserted `sms_messages` and `notifications` rows.</verify>
  <done>AC-1, AC-2, AC-3 and AC-5 persistence/backend behavior satisfied.</done>
</task>

<task type="auto">
  <name>Task 2: Add SMS settings UI and order conversation tab</name>
  <files>src/Modules/Settings/SmsplanetIntegrationController.php, src/Modules/Orders/OrdersController.php, resources/views/settings/smsplanet.php, resources/views/orders/show.php, resources/lang/pl.php, resources/scss/app.scss, public/assets/css/app.css, routes/web.php, DOCS/ARCHITECTURE.md, DOCS/TECH_CHANGELOG.md</files>
  <action>
    Build user-facing SMS controls:
    - Extend SMSPLANET settings form with a compact sender mode selector: text sender/nadpis or 2WAY number. Show both fields clearly and validate the required field based on selected mode.
    - Add order-level POST endpoint `/orders/{id}/sms/send` protected by auth and CSRF. It sends via SMSPLANET, stores the outbound message and redirects back to the order SMS tab with flash result.
    - Inject SMS messages into `OrdersController::show()` and render a separate `SMS` tab in `resources/views/orders/show.php`.
    - Conversation tab must show oldest-to-newest bubbles for inbound/outbound messages, timestamps, status/messageId for outbound, and a compact textarea form for sending a new message to the customer's phone.
    - Use existing alert component/Flash patterns and escape all output with `$e()`.
    - Put all styles in SCSS, then rebuild `public/assets/css/app.css`.
  </action>
  <verify>`C:\xampp\php\php.exe -l` on changed PHP files; `npm run build:css`; open order detail and verify SMS tab renders empty state, existing messages, and send form without layout overlap.</verify>
  <done>AC-1, AC-2 and AC-4 satisfied in UI.</done>
</task>

<task type="auto">
  <name>Task 3: Add global notification center with polling and browser notifications</name>
  <files>src/Modules/Notifications/NotificationController.php, src/Modules/Notifications/NotificationApiController.php, routes/web.php, resources/views/notifications/index.php, resources/views/layouts/app.php, public/assets/js/modules/notifications.js, resources/scss/app.scss, public/assets/css/app.css, resources/lang/pl.php, DOCS/ARCHITECTURE.md, DOCS/TECH_CHANGELOG.md</files>
  <action>
    Implement notification UX:
    - Add topbar notification icon/button with unread badge and link to `/notifications`.
    - Add authenticated `/notifications` page with paginated notification history, unread/read state, mark-read action and links to target URLs.
    - Add authenticated polling API endpoint, e.g. `/api/notifications/unread`, returning unread count and recent unread notification payloads.
    - Add optional mark-read API endpoint for clicked/opened notifications.
    - Implement `public/assets/js/modules/notifications.js` polling every 30 seconds, badge update, Notification API permission prompt on first user interaction with notification UI, and native browser notification for newly seen unread items when permission is granted.
    - Browser notification click should navigate to the notification target URL, usually `/orders/{id}?tab=sms`.
    - Keep JS progressive: page must work without browser notification permission.
  </action>
  <verify>`C:\xampp\php\php.exe -l` on notification controllers; `npm run build:css`; manually create an unread notification row and confirm topbar badge, `/notifications` page, polling update and browser notification behavior.</verify>
  <done>AC-5 and AC-6 satisfied.</done>
</task>

</tasks>

<boundaries>

## DO NOT CHANGE
- Do not add runtime usage of `DB_HOST_REMOTE`; runtime continues to use `DB_HOST`.
- Do not add native `alert()` or `confirm()` in views or JS; use existing alert module if confirmation/feedback is needed.
- Do not inline CSS in views; use `resources/scss/app.scss` and rebuild compiled CSS.
- Do not change existing email, invoice, receipt, shipment or automation contracts except for adding notification links where needed.
- Do not implement SMSPLANET webhook signature validation in this plan.

## SCOPE LIMITS
- Scope is SMSPLANET only; HostedSMS inbound replies remain out of scope.
- Matching inbound SMS is by latest order phone only; no order-code parser in message body.
- Notification transport is polling only; no WebSocket/SSE.
- No automation event for incoming SMS in this plan.
- No multi-user notification recipient model; global unread/read notifications are acceptable for this first version unless existing auth/user model makes per-user read state trivial.

</boundaries>

<verification>
Before declaring plan complete:
- [ ] `C:\xampp\php\php.exe -l` passes for all changed PHP files.
- [ ] `npm run build:css` completes and compiled CSS is updated.
- [ ] Migration applies on local MySQL when available.
- [ ] SMSPLANET settings save both sender modes and send test uses selected sender.
- [ ] Sample inbound webhook stores SMS and creates notification.
- [ ] Order detail SMS tab shows conversation and sends outbound SMS.
- [ ] Notification badge/page/polling/browser notification work in a browser that granted notification permission.
- [ ] `DOCS/DB_SCHEMA.md`, `DOCS/ARCHITECTURE.md`, `DOCS/TECH_CHANGELOG.md` updated.
- [ ] `sonar-scanner` attempted after APPLY; new issues recorded per `.paul/SPECIAL-FLOWS.md`.
</verification>

<success_criteria>
- Operator can configure SMSPLANET to send from nadpis or 2WAY number.
- Operator can receive SMSPLANET inbound replies into the latest matching order by phone.
- Operator can chat with customer from a dedicated SMS tab in order details.
- Inbound SMS creates a visible global notification and optional browser notification.
- No hardcoded test sender remains in production flow.
- All verification checks pass or environment-specific gaps are documented in SUMMARY.md.
</success_criteria>

<output>
After completion, create `.paul/phases/121-smsplanet-conversation-notifications/121-01-SUMMARY.md`.
</output>
