# Navagoo — Project Notes for Claude

## Active feature: Social Media Management (Upload-Post)

**Authoritative spec:** [`docs/features/social-media-management-brd.md`](docs/features/social-media-management-brd.md)

Always read the BRD first before changing anything in this feature. Any change in
behaviour or scope must update the BRD before code.

### Implementation map

| Layer | Files |
|---|---|
| Migration | `common/migrations/db/m260506_120000_add_social_media_tables.php` |
| Models | `common/models/{ShopSocialSettings,UploadPostProfile,SocialAccount,SocialPostingLimit,SocialPost,SocialAuditLog}.php` |
| Provider client | `common/components/UploadPostClient.php` · `UploadPostException.php` |
| Service layer | `common/components/SocialMediaService.php` (profile create, JWT mint, email-only delivery, account sync) |
| Email template | `common/mail/socialConnect.php` |
| Backend admin | `backend/controllers/ShopSocialController.php` · `backend/views/shop-social/{update,audit}.php` |
| Backend entry point | Social column + button on `backend/views/shop/index.php` (no separate menu item) |
| Shop dashboard | `frontend/controllers/SocialMediaController.php` · `frontend/views/social-media/{index,create,posts}.php` |
| API | `api/controllers/SocialController.php` (routes in `api/config/_urlManager.php`) |
| Status poller | `console/controllers/SocialPostStatusController.php` (cron-friendly; Upload-Post has no webhooks) |
| Config | `common/config/base.php` (`uploadPost`, `socialMedia` components) · `.env.dist` (`UPLOADPOST_*` vars) |

### Phase-1 platform allowlist
Exposed: **Instagram, TikTok, Facebook, YouTube, LinkedIn**.
BRD §5.2 lists the first four explicitly with "etc." — LinkedIn was added on top for B2B reach.
Locked in `common\models\ShopSocialSettings::ALLOWED_PLATFORMS`.

### Important behavioural decisions
- **Email-only delivery** of the linking URL (BR-04). The URL is *never* shown in any UI.
- **Quota counts successful posts only** (BR-08.9 / BR-09.9). Quota is consumed AFTER a
  successful provider call. Failed posts do not increment the counter.
- **Deleting published posts**: Upload-Post does not expose a delete-after-publish endpoint.
  Deleting a `STATUS_POSTED` row only removes it from Navagoo's history — the post stays
  on the social network and must be removed manually there. The counter is **not refunded**
  for already-published posts (the salon got their publication). Scheduled posts still get
  cancelled remotely via `cancelScheduled` before they fire.
- **Recalc counter logic** counts a post as consumed if it ever had `posted_at` set OR is
  currently in POSTED/SCHEDULED state. This correctly preserves the count for posts that
  were published then locally deleted.
- **Period defaults to 1 month**, set automatically on save. The "Quota period" UI card is
  hidden in the admin form for now (the `period_months` hidden input keeps the value).
- **Per-platform / per-account quotas** in `social_posting_limit`; resolution falls back to
  platform-default row (`social_account_id IS NULL`) when no per-account row exists.

### When iterating on this feature
1. Read the BRD section affected.
2. Update the BRD if scope changes.
3. Update code + translations (`common/messages/{ar,en}/{backend,frontend,common}.php`).
4. Bilingual is mandatory — every new `Yii::t('...', '...')` string must land in both
   `ar/*.php` and `en/*.php`.
