# درس: كيف يصل النظام إلى مستند الرخصة نفسه؟

هذا الدرس يشرح المسار الكامل من رقم القطعة أو الرخصة إلى تنزيل **مستند الرخصة وحده**، منفصلًا عن التقرير المساحي والمرفقات.

## 1. الفكرة في سطر واحد

الرخصة لها **مفتاح** (`lic/licYear`) وطلب مرتبط (`request/requestYear`). نطلب من الأمانة مرفقًا بنوع `type_attach=1`، فنحصل على Token مستقل، ثم ننزّل هذا Token عبر `PDFViewer.ashx`. وبما أن كل نوع له Token منفصل، يُحفظ كل نوع في PDF منفصل.

## 2. الخريطة

```mermaid
flowchart TD
  A[رقم القطعة أو الرخصة] --> B[استخراج المفتاح والطلب من licenses.db/comp]
  B --> C[GetRequestAttachment]
  C --> D[type_attach=1: مستند الرخصة]
  C --> E[type_attach=2/5: مرفقات وتقرير مساحي]
  D --> F[Token مستقل]
  E --> G[Token مستقل]
  F --> H[PDFViewer.ashx]
  G --> I[PDFViewer.ashx]
  H --> J[ملف الرخصة فقط]
  I --> K[ملف المرفقات]
```

## 3. البيانات المطلوبة

من جدول `comp` في `licenses.db`:

| الحقل | المعنى | مثال |
|---|---|---|
| `lic` | رقم الرخصة | 294 |
| `licy` | سنة الرخصة | 1411 |
| `req` | رقم الطلب | 124427 |
| `reqy` | سنة الطلب | 1447 |
| `parcel` | رمز القطعة | 13688228 |
| `pl` | المخطط/القطعة | 472\|9 |

**مهم:** لا تفترض أن سنة الرخصة = سنة الطلب. في المثال:

- الرخصة: `294/1411`
- الطلب: `124427/1447`

لذلك نقرأ `req` و`reqy` من `comp` أولًا. جدول `lic_req` قد لا يحتوي الرخصة القديمة، ورقم الرخصة نفسه قد يتكرر لسنوات وقطع مختلفة.

## 4. تسلسل الاستدعاءات

### الخطوة 1: الدخول العام

```http
POST https://mapservice.alriyadh.gov.sa/APIGEOPORTALN/api/login/authenticate
Content-Type: application/json
Apikey: <مفتاح مشتق من كلمة المرور والبادئة والوقت>

{"appid":"1"}
```

الاستجابة تحتوي `TOKEN`. يُستخدم بعد ذلك كـ`Authorization: Bearer <TOKEN>`.

النظام يبني `Apikey` عبر:

1. بادئة خاصة + وقت الطلب.
2. PBKDF2-SHA1 بكلمة مرور النظام.
3. AES-256-CBC بـSalt وIV عشوائيين.
4. Base64 للناتج.

لا توضع كلمة المرور أو البادئة داخل الواجهة أو أي ملف يوزّع للمستخدم.

### الخطوة 2: طلب مرفق الرخصة

```http
GET https://mapservice.alriyadh.gov.sa/APIGEOPORTALN/api/Public/GetRequestAttachment
    ?type_attach=1
    &Request_Number=124427
    &Request_Year=1447
Authorization: Bearer <TOKEN>
Apikey: <مفتاح مشتق>
Accept: application/json, text/plain, */*
```

الاستجابة الناجحة تكون Token نصيًا (وليس JSON)، مثل:

```text
9BC1CDEE22E546403CFA0B5CD6691DD0...
```

أنواع المرفقات:

| النوع | الاستخدام |
|---|---|
| `1` | مستند الرخصة |
| `5` | مرفقات/معاملات لاحقة |
| `2` | تقرير مساحي/مرفقات |
| `3`, `4` | أنواع إضافية إن وجدت |

### الخطوة 3: تنزيل الملف

```http
GET https://eservices.alriyadh.gov.sa/Handler/PDFViewer.ashx?<AttachmentToken>
User-Agent: Mozilla/5.0 ...
Referer: https://eservices.alriyadh.gov.sa/Pages/Viewer/DocumentsViewer
```

النظام يجرّب أولًا:

```text
https://eservices-pre.alriyadh.gov.sa
```

ثم الإنتاجي:

```text
https://eservices.alriyadh.gov.sa
```

مع `curl -C -` و3 محاولات، ثم `fetch` كبديل.

## 5. كيف يُفصل مستند الرخصة عن المرفقات؟

كل نوع له Token مستقل، وكل Token يُكتب في ملف مستقل:

```text
license-294-1411/
  294-1411-req124427-1447-1.pdf   ← type_attach=1
  294-1411-req124427-1447-5.pdf   ← type_attach=5 (إن وجد)
```

لا يُجمع الناتج في ملف واحد. لذلك يمكن تنزيل ملف الرخصة فقط.

في الواجهة:

- `مستند-الرخصة-294-1411.pdf` يظهر بشارة **«رخصة فقط»**.
- `المرفقات.pdf` يظهر بشارة **«مرفقات»**.
- ملف الرخصة يُرتَّب أولًا.

## 6. التحقق قبل قبول الملف

النظام يرفض:

| الحجم بالبايت | السبب |
|---:|---|
| 1,264 | صفحة نائبة |
| 5,160 | صفحة نائبة |
| 31,026 | صفحة نائبة |
| 33,536 | صفحة خطأ مؤقتة |
| 72,228 | صفحة خطأ مؤقتة |

ثم يتحقق من:

- توقيع `%PDF-`.
- أن الحجم ≥ 2,000 بايت.
- `pdfinfo` وعدد الصفحات ≥ 1.
- تصيير الصفحة الأولى عبر `pdftoppm`.

## 7. مثال حقيقي: الرخصة 294/1411

البيانات:

```text
license: 294/1411
request: 124427/1447
parcel: 13688228
plan/land: 472/9
```

مستند الرخصة المؤرشف:

```text
مستند-الرخصة-294-1411.pdf
الحجم: 2,987,614 بايت
الصفحات: 13
```

المرفقات منفصلة:

```text
المرفقات.pdf
الحجم: 37,849,796 بايت
الصفحات: 45
```

## 8. طلب الرخصة فقط من API

```bash
curl -X POST http://10.10.10.100/api/amanah/pull \
  -H 'content-type: application/json' \
  -d '{"license":"294","licYear":"1411","attachType":"1"}'
```

النتيجة المتحققة:

```json
{
  "files": [
    {
      "name": "294-1411-req124427-1447-1.pdf",
      "size": 37861134,
      "type": "1",
      "request": "124427/1447",
      "license": "294/1411"
    }
  ],
  "errors": []
}
```

لطلب المرفقات فقط:

```bash
curl -X POST http://10.10.10.100/api/amanah/pull \
  -H 'content-type: application/json' \
  -d '{"request":"124427","year":"1447","attachType":"5"}'
```

## 9. الروابط الجاهزة

- فتح القطعة: http://10.10.10.100/?id=13688228
- تنزيل مستند الرخصة فقط:
  http://10.10.10.100/api/pdf?p=%2Fmnt%2F99-data%2Fbls-search%2Fmnt%2Fresults%2F2026-10-13T14-29-18%2F13688228%2F%D9%85%D9%84%D9%81%D8%A7%D8%AA%2F%D8%B1%D8%AE%D8%B5%D8%A9-1411-294%2F%D9%85%D8%B3%D8%AA%D9%86%D8%AF%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D9%85%D8%A7%D9%86%D8%A9%2F%D9%85%D8%B3%D8%AA%D9%86%D8%AF-%D8%A7%D9%84%D8%B1%D8%AE%D8%B5%D8%A9-294-1411.pdf&dl=1

## 10. أخطاء شائعة وحلولها

| المشكلة | السبب | الحل |
|---|---|---|
| صفحة نائبة 31,026 | سنة الطلب خاطئة أو المرفق غير منشور في هذا النوع | جرّب سنة الرخصة/الطلب الصحيحة ونوعًا آخر |
| الرخصة 294/1411 غير موجودة في `lic_req` | الرخصة قديمة أو رقمها متكرر | اقرأ `req/reqy` من `comp` أولًا |
| طلب 124427/1411 بدل 124427/1447 | افتراض أن سنة الرخصة = سنة الطلب | استخدم `reqy` من `comp` |
| الملفان مدمجان | تنزيل كل الأنواع في ملف واحد | احفظ كل Token في ملف مستقل |
| ملف صغير 26 ك.ب يظهر غير حقيقي | حد أدنى 1 م.ب في تقرير الدفعة | التحقق الصحيح: PDF ≥ 2 ك.ب + صفحة واحدة |
| الرخصة لا تظهر في بطاقة القطعة | مجلد الرخصة غير مربوط بالقطعة | `/api/files` يضيف `license-*/request-*/manual-*` |

## 11. قائمة تحقق سريعة

- [ ] استخرجت `lic/licy` من الرخصة.
- [ ] استخرجت `req/reqy` من `comp` وليس بتخمين السنة.
- [ ] حصلت على Token الدخول.
- [ ] طلبت `type_attach=1` لمستند الرخصة.
- [ ] حصلت على Token مرفق مستقل.
- [ ] نزّلت عبر `PDFViewer.ashx`.
- [ ] تحققت من `%PDF-` والحجم و`pdfinfo`.
- [ ] حفظت الرخصة في ملف منفصل عن `type_attach=2/5`.
