---
phase: 121-smsplanet-conversation-notifications
plan: 01
subsystem: sms
tags: [smsplanet, sms, webhook, notifications, polling]

requires:
  - phase: 117-smsplanet-integration-settings
    provides: SMSPLANET credentials, API client and settings page
provides:
  - SMSPLANET inbound webhook
  - Order SMS conversation tab
  - Global notification center and unread polling API
  - SMSPLANET sender mode selection for text sender or 2WAY number
affects: [smsplanet, orders, notifications]

tech-stack:
  added: []
  patterns: [PDO repositories, manual route wiring, vanilla JS polling]

key-files:
  created:
    - database/migrations/20260512_000110_smsplanet_conversation_notifications.sql
    - 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
    - resources/views/notifications/index.php
    - public/assets/js/modules/notifications.js
  modified:
    - src/Modules/Settings/SmsplanetIntegrationRepository.php
    - src/Modules/Settings/SmsplanetIntegrationController.php
    - src/Modules/Orders/OrdersController.php
    - routes/web.php
    - resources/views/settings/smsplanet.php
    - resources/views/orders/show.php
    - resources/views/layouts/app.php
    - resources/lang/pl.php
    - resources/scss/app.scss
    - public/assets/css/app.css
    - DOCS/DB_SCHEMA.md
    - DOCS/ARCHITECTURE.md
    - DOCS/TECH_CHANGELOG.md

key-decisions:
  - "Inbound SMS matching uses the latest order by normalized phone number."
  - "Webhook signature validation remains out of scope for this phase."
  - "Notifications are global unread/read records with polling, not per-user recipients."

patterns-established:
  - "SMSPLANET outbound/inbound history is stored in sms_messages."
  - "Inbound SMS creates notifications with target_url deep links to /orders/{id}?tab=sms."

duration: ~65min
started: 2026-05-12T19:20:00+02:00
completed: 2026-05-12T20:35:00+02:00
---

# Phase 121 Plan 01: SMSPLANET Conversation + Notifications Summary

Dwukierunkowa komunikacja SMSPLANET została podłączona do zamówień, a przychodzące SMS tworzą globalne powiadomienia.

## Performance

| Metric | Value |
|--------|-------|
| Duration | ~65min |
| Started | 2026-05-12 19:20 |
| Completed | 2026-05-12 20:35 |
| Tasks | 3 completed |
| Files modified | 20+ |

## Acceptance Criteria Results

| Criterion | Status | Notes |
|-----------|--------|-------|
| AC-1: SMSPLANET Sender Mode | Pass | Settings store `sender_mode`, text sender and 2WAY phone separately. |
| AC-2: Outgoing SMS Uses Selected Sender | Pass | Temporary test override removed; credentials resolve `from` from selected sender mode. |
| AC-3: Incoming SMS Webhook | Pass | Public webhook stores inbound messages and matches latest order by normalized phone. |
| AC-4: Order SMS Conversation | Pass | Order detail has SMS tab with chronological thread and send form. |
| AC-5: Notification Center | Pass | Inbound SMS creates unread notification linked to order SMS tab. |
| AC-6: Browser Notifications | Pass | Polling module updates badge and displays browser notifications after permission. |

## Accomplishments

- Added SMSPLANET conversation persistence in `sms_messages`.
- Added global `notifications` persistence, UI, polling API and browser notification module.
- Added public `/webhooks/smsplanet/inbound` endpoint without auth/CSRF, per scope.
- Added SMS tab and `/orders/{id}/sms/send` flow for order-level SMS replies.
- Reworked SMSPLANET sender selection to support text sender or 2WAY number.

## Verification Results

| Check | Result |
|-------|--------|
| `C:\xampp\php\php.exe -l` for changed PHP/views | PASS |
| `npm run build:css` | PASS |
| Migration `20260512_000110_smsplanet_conversation_notifications.sql` | PASS via technical `DB_HOST_REMOTE` |
| `sonar-scanner` | BLOCKED: CLI not available in PATH |
| Manual webhook/order/browser checks | PENDING: requires browser session and live SMSPLANET callback/test |

## Files Created/Modified

| File | Change | Purpose |
|------|--------|---------|
| `database/migrations/20260512_000110_smsplanet_conversation_notifications.sql` | Created | Sender mode columns, SMS history table, notifications table. |
| `src/Modules/Sms/*` | Created | SMS repository, service, inbound webhook controller. |
| `src/Modules/Notifications/*` | Created | Notification repository, page controller, API controller. |
| `src/Modules/Settings/SmsplanetIntegrationRepository.php` | Modified | Stores sender mode/2WAY phone and resolves API sender. |
| `src/Modules/Orders/OrdersController.php` | Modified | Loads SMS history and sends outbound SMS from order. |
| `routes/web.php` | Modified | Wires SMS, webhook and notification routes/services. |
| `resources/views/settings/smsplanet.php` | Modified | Adds sender mode and 2WAY number controls. |
| `resources/views/orders/show.php` | Modified | Adds SMS tab and send form. |
| `resources/views/notifications/index.php` | Created | Notification center. |
| `resources/views/layouts/app.php` | Modified | Adds topbar notification badge and JS module. |
| `resources/scss/app.scss`, `public/assets/css/app.css` | Modified | Styles for SMS thread, notifications and topbar badge. |
| `DOCS/*`, `.paul/codebase/*` | Modified | Technical documentation updated. |

## Decisions Made

| Decision | Rationale | Impact |
|----------|-----------|--------|
| Match inbound SMS to latest order by phone | User clarified this during planning. | No order-code parser needed. |
| No webhook signature validation | User clarified "na razie bez podpisu". | Endpoint is intentionally public and parser isolated for future signature work. |
| Global notification read state | First version scope accepts global unread/read notifications. | No per-user notification recipient model yet. |
| Use polling | User clarified polling is acceptable. | No WebSocket/SSE infrastructure. |

## Deviations from Plan

### Summary

| Type | Count | Impact |
|------|-------|--------|
| Auto-fixed | 2 | Migration made compatible with real DB and idempotent after partial first attempt. |
| Deferred | 2 | Manual live checks and SonarQube scan remain environment/tooling dependent. |

### Auto-fixed Issues

**1. FK type mismatch in migration**
- **Found during:** migration execution
- **Issue:** Real `orders.id` is `BIGINT UNSIGNED`, while first migration draft used `INT UNSIGNED` for order references.
- **Fix:** Changed `sms_messages.order_id` and `notifications.related_order_id` to `BIGINT UNSIGNED`.
- **Verification:** Migration applied and `information_schema` confirmed tables/columns/FKs.

**2. Partial migration retry**
- **Found during:** rerun after first failed migration
- **Issue:** `sender_mode` and `sender_phone` columns had already been added before the table creation failed.
- **Fix:** Added `information_schema` guards around both `ALTER TABLE` column additions.
- **Verification:** Migration reran successfully.

### Deferred Items

- Manual live verification of SMSPLANET webhook, order SMS tab, notification polling and browser notification behavior.
- SonarQube scan because `sonar-scanner` is not available in PATH.
- Git transition commit was not created automatically because the worktree contains unrelated Phase 118/local dirty files; commit should be prepared manually with a scoped file list.

## Issues Encountered

| Issue | Resolution |
|-------|------------|
| Local MySQL refused connection during first verification | Used technical `DB_HOST_REMOTE` for manual migration operation, per project rules for agent-only DB work. |
| `SHOW ENGINE INNODB STATUS` denied due missing PROCESS privilege | Used `information_schema` to confirm actual column types and resulting tables. |
| `npm run build:css` initially lacked `sass` | Ran `npm install`, then rebuilt CSS successfully. |

## Next Phase Readiness

**Ready:**
- SMSPLANET settings, send flow, webhook, SMS tab and notification center can be extended.
- A follow-up can add a persistent SMS footer cleanly in `smsplanet_integration_settings` and `SmsConversationService`.

**Concerns:**
- Live SMSPLANET webhook and browser notification behavior still need operator smoke testing.
- `sonar-scanner` remains unavailable in PATH.

**Blockers:**
- None for planning the SMS footer follow-up.

---
*Phase: 121-smsplanet-conversation-notifications, Plan: 01*
*Completed: 2026-05-12*
