# Project Changelog — دليل مدينتي / Daleel Madinati

> **The project's build history — one section per completed sprint (newest on top).**
> Written at each sprint's Definition of Done (DoD). It records what shipped, the key files, the
> decisions, and the DoD result — so anyone (human or agent) can see *what happened, sprint by sprint*
> without reading the code. Complements `CONTEXT.md` (orientation) and the root `README.md` (external face).

<!-- Entry template — prepend a new one at the top when a sprint passes DoD:

## Sprint <n> — <title>   ·   `<commit-hash>`   ·   <date>
- **Shipped:** <endpoints / CRUDs / features delivered>
- **Key files:** <controllers · services · models · migrations · resources · routes · lang>
- **Decisions / new patterns:** <what future sprints should mirror — also add to CONTEXT §C if reusable>
- **DoD:** migrate ✅ · pint ✅ · dump-autoload ✅ · schema:check ✅ · tests ✅ (<count>) · smoke ✅

-->

## الإيميل من تحديث الملف   ·   2026-10-05
- **Shipped:** الباحث يغيّر الإيميل في `PATCH /api/v1/user/profile`، ومقدم الخدمة في `PATCH /api/v1/provider/auth/me`. لا دورة تحقق منفصلة. مسار `/api/v1/profile/change-email/*` أُزيل. تغيير الجوال يبقى كما هو.
- **Key files:** `User/Profile/UpdateRequest` · `Provider/Auth/UpdateRequest` · `UserProfileService` · `ProviderAuthService`

## إشعارات الرئيسية وإلغاء اشتراك الأعمال   ·   2026-10-05
- **Shipped:** `is_notify` على `PATCH /api/v1/user/profile` و`PATCH /api/v1/provider/auth/me`. الإشعار يبقى في قاعدة البيانات، وFCM لا يُرسل عندما تكون القيمة `false`. `GET /api/v1/user/home` يرجع قسم `interviews` بنفس قائمة `GET /user/interviews`. `POST /api/v1/provider/subscriptions/{id}/cancel` يلغي اشتراك مقدم الخدمة.
- **Key files:** `UserProfileService` · `ProviderAuthService` · `HomeController` · `Provider/Billing/CancelController` · `UserResource` · `ProviderResource`
- **DoD:** tests ✅ (`ProfileTest` · `JobsTest` · `BillingTest` · `AuthTest`)

## دخول بالجوال ورمز التحقق فقط   ·   2026-10-05
- **Shipped:** الباحث ومقدم الخدمة لا يرسلان ولا يستقبلان كلمة مرور. الدخول `POST /api/v1/user/auth/request-code` ثم `verify-otp`، ونفس المسارين تحت `provider/auth`. أُزيلت مسارات login وكلمة المرور المنسية وتغيير كلمة المرور، وطلبات Postman المقابلة.
- **Key files:** `routes/api/v1/{user,provider,auth,profile}.php` · `UserAuthService` · `ProviderAuthService` · `docs/postman/daleel-hr.postman_collection.json`
- **Decisions:** عمود `password` يبقى في الجدول (nullable ومخفي). نماذج الأدمن للباحث ومقدم الخدمة لم تعد تطلب كلمة مرور. كلمة مرور المشرف تبقى.

## إشعارات kite + FCM   ·   2026-10-05
- **Shipped:** شكل إشعار ثنائي اللغة (`title`/`message`) + `notification_type` ومعرفات الكيان. إرسال FCM HTTP v1 عبر `FirebaseV1Trait` عند وجود أجهزة و`is_notify`. جدول `devices` morph + مزامنة التوكن عند login/verify-otp/register. `NotificationResource` يرجع `title`/`body`/`is_read`/`data`.
- **Key files:** `FirebaseV1Trait` · `UserNotification` · `Device` · `DeviceService` · `NotificationResource` · hiring/admin notification dispatches · `tests/Feature/Api/NotificationsTest.php`
- **DoD:** migrate ✅ · tests ✅ (`NotificationsTest` 4 · `AuthTest` 13)

## حالة الطلب وحالة الوظيفة   ·   2026-10-01
- **Shipped:** حالة الطلب `new` / `under_review` / `under_study` / `rejected`. حالة الوظيفة في الرد تُحسب حسب المشاهد. الوظيفة تُحفظ فور الإضافة، وتظهر من `starts_at` حتى قبل `expires_at`، وتختفي عن غير المتقدمين بعد الإغلاق. `POST /api/v1/provider/applications/{id}/review` ثم `accept` ثم `reject`.
- **Key files:** `ApplicationStatus` · `CandidateService` · `JobPost` · `ProviderJobPostService` · `JobPostBrowseService`

## حالة التقديم وتواريخ الوظيفة   ·   2026-10-01
- **Shipped:** حالة الطلب `new` / `under_review` / `under_study` / `rejected`. حالة الوظيفة في الرد تُحسب حسب المشاهد. الوظيفة تُضاف فورًا وتظهر من `starts_at` حتى قبل `expires_at`. بعد الانتهاء تختفي عن غير المتقدمين. لا مسودة ولا نشر ولا إغلاق يدوي.
- **Key files:** `ApplicationStatus` · `CandidateService` · `JobPost` · `JobPostBrowseService` · `ProviderJobPostService`

## نوع حساب مقدم الخدمة بعد الدخول   ·   2026-10-01
- **Shipped:** التسجيل من غير `password` ومن غير `provider_type`. `GET /api/v1/provider/auth/provider-types` يرجع الخيارات السبعة. `PATCH /api/v1/provider/auth/provider-type` يحفظ الاختيار.
- **Key files:** `ProviderType` · `ProviderTypeIndexController` · `ProviderTypeUpdateController` · `UpdateProviderTypeRequest`

## قطاع وحجم الشركة في التسجيل   ·   2026-10-01
- **Shipped:** `sector` و `company_size` مطلوبان في `POST /api/v1/provider/auth/register` ويرجعان مع الحساب. لا طلب جديد.
- **Key files:** `RegisterRequest` · `ProviderAuthService` · `ProviderResource` · migration `2026_10_01_120000_add_company_profile_fields_to_providers_table`

## تغيير جوال مقدم الخدمة   ·   2026-09-30
- **Shipped:** `POST /api/v1/provider/auth/change-phone/request-current-code` ثم `verify-current` ثم `set-new` ثم `verify-new`. نفس دورة الباحث، على حساب مقدم الخدمة.
- **Key files:** `Provider/Profile/ChangePhone/*` · `ChangePhoneService` · `Provider/Profile/SetNewPhoneRequest`

## إضافة وظيفة دفعة واحدة   ·   2026-09-30
- **Shipped:** `POST /api/v1/provider/job-posts` ينشئ الوظيفة بحقول الخطوات الثلاث معاً. `step-1` و `step-2` و `step-3` كما هي. `publish=1` أو غيابه ينشر الوظيفة، و `0` يبقيها مسودة.
- **Key files:** `Provider/Jobs/StoreController` · `StoreRequest` · `ProviderJobPostService::store`
- **DoD:** pint ✅ · tests ✅ JobsTest

## تأكيد السيرة والمجالات المهنية   ·   2026-09-30
- **Shipped:** `POST /api/v1/user/profile/cv-data` يحفظ الملخص والخبرات والمؤهلات و`skill_ids` من قائمة الأدمن والشهادات دفعة واحدة · `GET/PUT /api/v1/user/career-fields` مجالات مقترحة وأخرى · `POST /api/v1/user/cv/generate` و `analyze` و `improvements/apply` يبني سيرة PDF ويحلّل الفجوات ويكتب التحسينات المقبولة ثم يعيد الإصدار
- **Key files:** `CvDataService` · `CareerFieldService` · `CvDocumentService` · `User/Profile/CvDataController` · `CareerFieldController` · `User/Cv/*` · `database/migrations/hiring/2026_09_30_120000_add_cv_onboarding_tables.php`
- **Decisions / new patterns:** لا نموذج ذكاء. الاقتراح مطابقة نصية مع `job_title` والمؤهلات والخبرات والمهارات (حتى 4). زر التجربة يبقى اشتراك `trial` الحالي. **تخطي الآن** بلا طلب.
- **DoD:** migrate ✅ · pint ✅ · tests ✅ ResumeOnboardingTest 4 (34)

## الوظائف المستهدفة — قائمة متوافقة   ·   2026-09-28
- **Shipped:** `GET /api/v1/user/target-jobs` يعرض وظائف `active` المتوافقة مع مدينة الباحث أو مهاراته أو `job_title` · حذف `POST`/`DELETE` وجدول `target_jobs`
- **Key files:** `JobPostBrowseService::matching` · `JobApplicationService::matchPercent` · `User/Profile/TargetJobController` · `database/migrations/hiring/2026_09_28_110000_drop_target_jobs_table.php`
- **Decisions / new patterns:** لا pattern جديد · التوافق = مهارات 60 + مدينة الملف 25 + تطابق `users.job_title` 15 · اكتمال الملف من 6 أقسام
- **DoD:** migrate ⏭ (هجرة drop جديدة، بدون fresh) · pint ✅ · tests ✅ 53 Feature/Admin+Api (303)

## إصلاح داشبورد الأدمن   ·   2026-09-27
- **Shipped:** جداول hiring/billing بأعمدة صحيحة + switchActive/switchBlock + إلغاء اشتراك + صفحات show + إحصائيات مطابقة للمتحكم + تقارير funnel/purpose/audience + home KPIs + فلتر title للوظائف + فك JSON لفلاتر طلبات الترشيح
- **Key files:** `resources/views/admin/{providers,skills,jobposts,jobapplications,interviews,plans,subscriptions,candidaterequests}/*` · `JobPost::applyColumnFilter` · `ProviderService::index` · `admin-table.js`
- **DoD:** migrate ⏭ · pint ✅ · dump-autoload ✅ · tests ✅ 52 Feature/Admin+Api (305)

## بعد سبرنت 8 — إشعارات مقدّم الخدمة   ·   2026-09-27
- **Shipped:** `GET /api/v1/provider/notifications` — نفس شكل قائمة الباحث (paginate + NotificationResource)
- **Key files:** `Api/V1/Provider/Notifications/IndexController` · `Requests/Api/Provider/Notifications/IndexRequest`
- **DoD:** pint ✅ · tests عبر SupportTest

## Sprint 8 — لوحة الأدمن + التقارير + الدعم   ·   2026-09-27
- **Shipped:** توسيع users · CRUDs لـ providers/jobcategories/skills/jobposts/jobapplications/interviews/plans/subscriptions/candidaterequests · home KPIs · تقارير توظيف/اشتراكات + CSV · `POST /api/v1/{user,provider}/complaints` · `GET /api/v1/user/notifications`
- **Key files:** `app/Services/Admin/{DashboardHome,Report,*Service}.php` · `app/Services/Support/ComplaintApiService.php` · `Admin/{JobCategory,Plan,Report}Controller` · `lang/{ar,en}/admin/{home,routes,main}.php` · `lang/{ar,en}/api/support.php`
- **Decisions / new patterns:** لا pattern جديد — Country/User admin · سعر الباقة من الأدمن (`price_minor`) · book_value = Σ خطط الاشتراكات النشطة/التجربة · شكوى morph `complaiantable` وعمود `complaint` = message
- **DoD:** migrate ⏭ · pint ✅ · dump-autoload ✅ · schema:check ⏭ (cms فارغ + DB ملوّثة) · tests ✅ 52 Feature/Api+Admin (301) · smoke عبر الاختبارات

## Sprint 7 — الباقات والاشتراكات   ·   2026-09-27
- **Shipped:** user plans/subscribe/skip-trial/me/cancel · provider plans/subscribe/me — بدون بوابة دفع
- **Key files:** `app/Services/Billing/BillingService.php` · `Api/V1/{User,Provider}/Billing/*` · `PlanResource` · `SubscriptionResource` · `lang/{ar,en}/api/billing.php`
- **Decisions / new patterns:** subscribe = trial 30 يوم ثم `ends_at` حسب interval · اشتراك واحد نشط لكل حساب (409) · skip-trial: trial→active بدون charge
- **DoD:** migrate ⏭ · pint ✅ · dump-autoload ✅ · tests ✅ 49 Feature/Api (280)

## Sprint 6 — المقابلات والمرشحون   ·   2026-09-27
- **Shipped:** user interviews accept/reject · provider candidates by-job/show/accept/reject/search · candidate-requests · interview schedule
- **Key files:** `app/Services/Hiring/{Interview,Candidate,CandidateRequest}Service.php` · `Api/V1/{User/Interviews,Provider/Candidates,Provider/Interviews}`
- **Decisions / new patterns:** ملف المرشح بدون national_id/nafath_raw · طلب ترشيح يبقى pending للأدمن · إشعار الجدولة/القرار عبر SendNotificationJob
- **DoD:** migrate ⏭ · pint ✅ · tests ✅ 44 Feature/Api (238)

## Sprint 5 — الوظائف والتقديمات   ·   2026-09-27
- **Shipped:** job-categories · user home/list/show/apply · applications index/show/withdraw · provider 3-step publish + list/show/update/close
- **Key files:** `app/Services/Hiring/*` · `Api/V1/User/Jobs/*` · `Api/V1/Provider/Jobs/*` · `routes/api/v1/{user,provider,job-categories}.php`
- **Decisions / new patterns:** `match_percent` = تقاطع مهارات 60 + نفس المدينة 25 + تطابق عنوان target_jobs 15 · إشعار الشركة عبر `SendNotificationJob` · لا Calculator منفصل
- **DoD:** migrate ⏭ · pint ✅ · dump-autoload ✅ · tests ✅ 42 Feature/Api (212) · smoke عبر الاختبارات

## Sprint 4 — ملف الباحث + الوسائط   ·   2026-09-27
- **Shipped:** skills lookup · personal profile · educations/experiences/certificates CRUD · skills sync · CV/intro video · target jobs · profile completion
- **Key files:** `routes/api/v1/{user,skills}.php` · `app/Http/Controllers/Api/V1/User/Profile/*` · `UserProfileService` · `bootstrap/app.php` (SubstituteBindings على API)
- **Decisions / new patterns:** اكتمال الملف = 7 أقسام / عتبة 70% ترفع `is_complete_info` فقط ولا تخفضه · لا Observer
- **DoD:** migrate ⏭ (DB ملوّثة) · pint ✅ · dump-autoload ✅ · schema:check ⏭ hiring unchanged · tests ✅ 35 Feature/Api (169) · smoke عبر الاختبارات ar+en

## Sprint 3 — مصادقة الباحث والشركة + نفاذ stub   ·   2026-09-27
- **Shipped:** lookups (cities/countries) · pages/faqs · locale · user auth (OTP/register/login/activate/nafath stub/me/logout/delete) · provider auth (register/login/OTP/me/update/logout/delete)
- **Key files:** `routes/api/v1/{user,provider,content}.php` · `app/Http/Controllers/Api/V1/{User,Provider}/Auth/*` · `UserAuthService` · `ProviderAuthService` · `NafathStubService`
- **Decisions / new patterns:** حراسة `auth:user` / `auth:provider` · نفاذ Cache stub بدون HTTP خارجي · `?lang=` يتقدّم على Accept-Language
- **DoD:** migrate ⏭ (DB ملوّثة محلياً — نفس سبرنت 1) · pint ✅ · dump-autoload ✅ · schema:check hiring ✅ (cms فارغ + جداول غريبة pre-existing) · tests ✅ 23 Feature/Api · smoke عبر الاختبارات ar+en

## START — الخطط (API / CRUD / sprints)   ·   2026-09-27
- **Shipped:** 83 خطة API + 12 CRUD/home/reports + sprints 3–8 + هيكل Postman + `board:sync`. **بدون** تنفيذ endpoints/CRUD/tests.
- **Key files:** `docs/project/api/{shared,user,provider}/**` · `docs/project/cruds/*` · `docs/project/sprints/{3–8}.md` · `docs/postman/daleel-hr.postman_collection.json`
- **Decisions:** سبرنت 3 مصادقة الجمهورين + نفاذ stub · 4 ملف · 5 وظائف/تقديم · 6 مقابلات/مرشحون · 7 باقات بدون دفع · 8 أدمن. سبرنت 1–2 تبقيا done من الـ base.
- **DoD:** خطط فقط — التنفيذ بعد مراجعة المطوّر

## START — طبقة الداتا بيز   ·   2026-09-27
- **Shipped:** schema `hiring` + migrations/models/factories/seeders لـ providers، job_posts، الملف، التقديمات، المقابلات، الباقات. ALTER users. موقع تعريفي بهوية دليل مدينتي.
- **Key files:** `database/migrations/hiring/*` · `app/Models/{Provider,JobPost,…}` · `database/schema/hiring.json` · `config/auth.php` (guard `user`/`provider`)
- **Decisions:** `job_posts` بدل `jobs` (تعارض طابور Laravel) · أسعار الباقات من الأدمن · نفاذ stub · لا جداول بطاقة
- **DoD:** migrate ✅ · pint ✅ · dump-autoload ✅ · schema:check ✅ · tests ⏭ · smoke: factory delete ✅

_No sprints completed yet._
