إنتقل إلى المحتوى الرئيسي

دفتر العناوين

الخلفية​

على Shukah يحتفظ التطبيق بعناوين التوصيل المحفوظة للعميل عبر خمسة استدعاءات على /maeda/address-book (المسار لا يحتوي الجزء /api/): list وget وcreate وupdate وdelete. وفي خدمة المصادقة الـ routes الخمسة نفسها، لكنها ليست بديلًا مباشرًا (drop-in). وأربعة أمور تستحق العناية: أن id العنوان سلسلة من 24 حرفًا بدل عدد صحيح، وأن إجابتَي list وcreate لهما شكل مختلف عن إجابتَي get وupdate، وأن create يجيب داخل غلاف {status, address}، وأن استدعاء create لا يملأ الشارع والمدينة وسائر أجزاء العنوان التي تشتقها Shukah بنفسها.

الميزة​

يتيح التطبيق للعميل المسجَّل الدخول أن يحتفظ بعدة عناوين محفوظة ويختار أحدها عنوانًا افتراضيًا. وفي نسخة التطبيق اللحظية بتاريخ 2026-02-26 تحدث الاستدعاءات في هذه الأماكن:

الاستدعاءأين في التطبيق
Listعندما يفتح عميل مسجَّل الدخول شاشة تعرض العناوين المحفوظة (درج المواقع وشريط موقع المستخدم) ولم تُحمَّل القائمة بعد، وعندما يهيّئ التطبيق عنوان التوصيل الافتراضي بعد تسجيل الدخول، وعند السحب للتحديث (pull-to-refresh) في قائمة العناوين المحفوظة، ومرة أخرى بعد كل create أو update أو delete.
Getعندما يفتح العميل شاشة تعديل العنوان.
Createعندما يحفظ العميل موقعًا من الخريطة مع تفعيل «حفظ لوقت لاحق». وإذا وُجد عنوان محفوظ بالاسم نفسه، يحذفه التطبيق أولًا ثم ينشئ العنوان الجديد.
Updateعندما يحفظ العميل شاشة تعديل العنوان. يرسل التطبيق location_name وarea وis_default وimage_urls.
Deleteعندما يحذف العميل عنوانًا في شاشة تعديل العنوان.

تحتاج الاستدعاءات الخمسة كلها إلى JWT من Locate (انظر «الحصول على token تجريبي» في النظرة العامة للوحدة). وهذه القواعد تنطبق عليها جميعًا:

  • المعرّفات (Ids). كل استجابة تعطي المعرّف بوصفه Mongo ObjectId: سلسلة hex من 24 حرفًا. وفي مسار get وupdate وdelete، تُجرَّب القيمة المكوَّنة من أرقام فقط أولًا بوصفها معرّف عنوان Shukah القديم، ثم بوصفها ObjectId. وأي قيمة أخرى تُجرَّب بوصفها ObjectId فقط. ولا يحمل معرّف Shukah إلا العناوين التي جاءت من دفتر عناوين Shukah، ولا تُظهره أي استجابة أبدًا.
  • شكلان للاستجابة. يستخدم List وcreate شكل القائمة (list shape): فـ is_default قيمة منطقية (boolean)، وlat وlng أرقام، والحقل النصي المفقود null، وتوجد مفاتيح source وcreated_at و updated_at. ويستخدم Get وupdate شكل التفصيل (detail shape): فـ is_default هو 0 أو 1، وlat و lng سلاسل نصية، والحقل النصي المفقود ""، وهذه المفاتيح الثلاثة غائبة.
  • القيم الفارغة. في create وupdate يُحذف الفراغ الزائد من الحقل النصي، وتُخزَّن القيمة الفارغة null. وتُخزَّن lat أو lng الفارغة أو غير الرقمية null. ولا يُتحقق من أي شيء: فالـ body الفارغ ينشئ عنوانًا بكل حقوله فارغة، ولا حد لعدد العناوين.
  • التحديث الجزئي. يغيّر Update المفاتيح الموجودة في الـ body فقط. والمفتاح الموجود بالقيمة null أو "" أو مسافات فقط يمسح الحقل (وتصبح image_urls []). أما source ومعرّف Shukah و created_at فلا تتغير أبدًا.
  • عناوينه هو فقط. يُبحث عن المعرّف بين عناوين المستدعي فقط. والمعرّف الذي يخص شخصًا آخر، أو لا يخص أحدًا، يعطي 404 مع Address not found.
  • عنوان افتراضي واحد. تُبقي الخدمة عنوانًا افتراضيًا واحدًا عندما ينشئ التطبيق أو يحدّث أو يحذف:
الاستدعاءالقاعدة
Createis_default بقيمة true تمسح العلامة عن كل عنوان آخر. وإلا يصبح العنوان الجديد هو الافتراضي فقط عندما يكون الدفتر فارغًا أو بلا عنوان افتراضي.
Updateفقط عندما يحتوي الـ body على is_default. عند ضبطها true: يفقد كل عنوان آخر العلامة. وعند ضبطها false بينما لا يوجد عنوان آخر افتراضي: يصبح أول عنوان آخر هو الافتراضي. وإذا كان العنوان هو الوحيد، يبقى هو الافتراضي.
Deleteإذا لم يبقَ عنوان افتراضي والدفتر غير فارغ، يصبح أول عنوان بترتيب التخزين هو الافتراضي. والقائمة مرتبة بالتاريخ، لذا ليس هذا دائمًا أول عنوان يراه التطبيق.

هذا الضمان يسري على هذه الاستدعاءات الثلاثة فقط. فالعناوين المنسوخة من Shukah لا تُفحص، وعلى dev كانت جميع العناوين العشرة في القائمة الملتقطة افتراضية (انظر كتلة list).

GET /api/v1/clients/address-book​

يستبدل ShukahGET /maeda/address-book✅ تم الاستبدال
يحتاج تعديل التطبيق2 breaking · 5 للمراقبة
  • 🔴 يحصل token من Shukah على 401 "Unauthorization"؛ أرسل JWT من Locate (من exchange-token؛ واحتفظ بـ token من Shukah).
  • 🔴 العناوين التي تُنشأ على Locate قيم formatted_address وstreet وcity فيها null؛ ويرسل التطبيق formatted_address كـ c_address.
  • 🟡 id سلسلة hex من 24 حرفًا (وهو عدد صحيح في Shukah)؛ ولم يعد معرّف Shukah المحفوظ يطابق (initLocation.ts:78).
  • 🟡 is_default من نوع boolean وقيمته true في 28 من 30 (في Shukah القيمة 0 في كل الـ 15)؛ ويأخذ initLocation أول عنصر قيمته true.
  • 🟡 30 عنوانًا مقابل 15 على Shukah: لا تصل عمليات الحذف في Shukah إلى Locate، ويظهر "Saihat" 3 مرات.
  • 🟡 قيمة image_urls هي [] على Locate لكل عناوين Shukah الأربعة التي لها صورة (وتُرجع Shukah الرابط).
  • 🟡 ترتّب Locate بحسب created_at الأحدث أولًا؛ وترتّب Shukah بحسب position (0..14)، لذا قد يتغير ترتيب القائمة.

تُرجع Locate القيمة is_default كـ boolean والمعرّف id كسلسلة hex من 24 حرفًا، بينما تُرجع Shukah القيمة 0 أو 1 ومعرّف id عددًا صحيحًا (و lat وlng أرقام على الجانبين)؛ ويقبل فحص الافتراضي في التطبيق الـ boolean، لكن أي شيء يعامل المعرّف كرقم يجب تغييره.

الطلب (Request)​

الحقلالموضعالنوعمطلوبالقيودالوصف
AuthorizationheaderstringنعمBearer <locate-jwt>. وtoken من Shukah يحصل على 401.الـ JWT من Locate.
أي مفتاح query أو header آخرquery، header—لايُقبل ويُتجاهل، مثل language.—

لا ترقيم للصفحات (paging) ولا مرشّح ولا خيار ترتيب.

الاستجابة (Response)​

200 مع مصفوفة بشكل القائمة. وهي [] عندما لا يكون للعميل عنوان. ويأتي أحدث created_at أولًا، وتأتي العناوين التي بلا created_at أخيرًا.

الحقلالنوعيقبل nullالصيغة / القيودالوصف
idstringلاObjectId من 24 حرف hex. وليس أبدًا معرّف Shukah العددي.معرّف العنوان لـ get وupdate وdelete.
sourcestringنعمmt_client_inline أو mt_address_book أو locate.مصدر العنوان: locate لعنوان أُنشئ عبر هذا الـ API.
is_defaultbooleanلاtrue أو false. ويمكن أن يكون أكثر من عنوان true.العنوان الافتراضي.
location_name وstreet وarea وarea_name وcity وstate وzipcode وcountry وcountry_code وformatted_addressstringنعمnull عند الغياب. والسلسلة الفارغة المخزَّنة بالفعل تبقى "" (في الالتقاط state: "").أجزاء العنوان.
lat وlngnumberنعمأرقام JSON. لا فحص للمدى.الإحداثيات.
image_urlsarray of stringلامصفوفة دائمًا، وقد تكون فارغة.عناوين URL للصور.
created_at وupdated_atstringنعمISO 8601 بتوقيت UTC، مثل 2026-09-29T17:01:10.000Z.وقت إنشاء العنوان وآخر تغيير له.
[
{
"id": "6abbeed8a492ed4862500b74",
"source": "mt_address_book",
"is_default": true,
"location_name": "Saihat",
"street": "King Fahd Rd",
"area": "Eastern Province",
"area_name": "A12345",
"city": "Saihat",
"state": "Al-Qatif",
"zipcode": "32461",
"country": "Saudi Arabia",
"country_code": "SA",
"lat": 24.7136,
"lng": 46.6753,
"formatted_address": "King Fahd Rd, Al Olaya, Riyadh 12211",
"image_urls": [],
"created_at": "2026-09-29T17:01:10.000Z",
"updated_at": "2026-09-29T17:01:10.000Z"
}
]

التُقط على dev، 2026-10-01 (العميل 356259): أول عنصر من 28 عنصرًا، واستُبدلت الحقول الشخصية والإحداثيات.

الأخطاء​

HTTPBodyمتى
401{"status":401,"message":"Unauthorization"}لا يوجد token، أو الـ token ليس JWT من Locate، أو العميل مفقود أو غير نشط. الحارس نفسه الخاص بـ التحقق من الـ token.
401الـ body نفسه.الـ token صالح لكن تعذّر تحميل سجل العميل.
500على dev: {"status":500,"message":"<raw error text>","stack":"<stack trace>"}. وفي production: {"status":500,"message":"Internal server error"}.فشل غير متوقع. لم يُلتقط. وعلى dev تكون الرسالة نص الخطأ الخام ويُضاف حقل stack؛ ولا تظهر Internal server error إلا في production (UAT وproduction: غير موثّق بعد).

التُقط body الخاص بـ 401 على dev في 2026-10-01 دون token.

جرّبه​

export AUTH_BASE_URL=https://dev.authentication.locate.sa
export TOKEN='<locate-jwt>' # see "Getting a test token" on the module overview
curl -s "$AUTH_BASE_URL/api/v1/clients/address-book" -H "Authorization: Bearer $TOKEN"

المتوقع: 200 ومصفوفة مثل المبيّنة تحت «الاستجابة». وبلا token تحصل على 401 المبيّن تحت «الأخطاء».

الفروق عن Shukah​

الجانبShukahLocateالأثر على التطبيق
URLGET $SHUKAH_BASE_URL/maeda/address-bookGET $AUTH_BASE_URL/api/v1/clients/address-bookغيّر base URL والمسار.
الـ Tokentoken معتم (opaque) من Shukah.JWT من Locate فقط.احصل على الـ JWT عبر exchange-token أولًا، واحتفظ بـ token Shukah لـ order-v2. ولا تنقل تسجيل الدخول إلى Locate بعد.
idعدد صحيح، مثل 162115 (التُقط على dev، 2026-10-01).سلسلة من 24 حرفًا، مثل 6abbeed8a492ed4862500b74.يجب تغيير أي شيء يخزّن المعرّف أو يقارنه بوصفه رقمًا. والتطبيق يعرّفه كرقم.
is_default0 أو 1 (التُقط على dev، 2026-10-01).true أو false.يجد التطبيق العنوان الافتراضي باختبار truthiness، وهو يعمل مع الاثنين. لكن المقارنة الصارمة مع 1 لن تعمل.
مفاتيح إضافيةposition (عدد صحيح).source وcreated_at وupdated_at؛ ولا position.لا شيء: فنوع العنوان في التطبيق لا يحتوي أيًّا من هذه المفاتيح الأربعة.
image_urlsمصفوفة أو null. أربعة من 15 عنوانًا للعميل لها URL صورة (التُقط على dev، 2026-10-02).مصفوفة دائمًا. والنسخ على Locate من هذه العناوين الأربعة فيها [].تضيع صور العناوين المنسوخة من Shukah. السبب: غير موثّق بعد.
الترتيبحسب position، من 0 إلى 14، بينما المعرّفات ليست مرتبة (162115 و161996 و162101 و…) (التُقط على dev، 2026-10-02).الأحدث created_at أولًا.إذا كان التطبيق يعرض القائمة بترتيب الخادم، فسيتغير الترتيب.
العدد للعميل 35625915 عنوانًا (التُقط على dev، 2026-10-02؛ و13 في 2026-10-01).30 عنوانًا، للعميل نفسه واليوم نفسه (و28 في 2026-10-01).العناوين المحذوفة على Shukah تبقى على Locate، ويظهر عنوان واحد ثلاث مرات على Locate. افحص التكرارات قبل التحوّل.
العناوين الافتراضيةis_default يساوي 0 في العناوين الـ15 كلها (التُقط على dev، 2026-10-02).true في 28 من 30.يأخذ التطبيق أول عنوان افتراضي يجده، لذا قد يختلف العنوان الافتراضي المحدَّد.

GET /api/v1/clients/address-book/:id​

يستبدل ShukahGET /maeda/address-book/:id✅ تم الاستبدال
يحتاج تعديل التطبيق1 breaking · 5 للمراقبة
  • 🔴 يحصل token من Shukah على 401 "Unauthorization"؛ أرسل JWT من Locate (من exchange-token؛ واحتفظ بـ token من Shukah).
  • 🟡 id سلسلة hex من 24 حرفًا؛ ولا يزال معرّف Shukah العددي (162115) يُحلّ في المسار.
  • 🟡 lat وlng سلسلتان نصيتان (أرقام في Shukah)؛ ويستخدم التطبيق Number() (locationPresetToSelectedAddress.ts:14).
  • 🟡 العنوان نفسه: is_default يساوي 1 على Locate مقابل 0 على Shukah، وimage_urls هي [] مقابل رابط صورة (162115).
  • 🟡 معرّف يخص شخصًا آخر: Locate تعطي 404 "Address not found"؛ وShukah تعطي 403 "You can only view address that belong to you."
  • 🟡 يحمل body الـ 404 في Locate قيمة stack من الخادم (get.js:39:17) على dev.

الطلب (Request)​

الحقلالموضعالنوعمطلوبالقيودالوصف
AuthorizationheaderstringنعمBearer <locate-jwt>.الـ JWT من Locate.
idpathstringنعمالقيمة المكوَّنة من أرقام فقط تُجرَّب أولًا بوصفها معرّف عنوان Shukah، ثم بوصفها ObjectId. وأي شيء آخر يُجرَّب بوصفه ObjectId فقط.معرّف العنوان.
أي مفتاح query أو header آخرquery، header—لايُقبل ويُتجاهل.—

الاستجابة (Response)​

200 مع عنوان واحد بشكل التفصيل، دون غلاف:

الحقلالنوعيقبل nullالصيغة / القيودالوصف
idstringلاالـ ObjectId، حتى لو استُخدم معرّف Shukah العددي في المسار.معرّف العنوان.
location_name وformatted_address وarea_name وstreet وcity وarea وstate وzipcode وcountry وcountry_codestringلا"" عند الغياب، وليس null أبدًا.أجزاء العنوان.
is_defaultintegerلا0 أو 1.العنوان الافتراضي.
lat وlngstringلاالرقم كنص، مثل "24.7136". و"" عند الغياب.الإحداثيات.
image_urlsarray of stringلاقد تكون فارغة.عناوين URL للصور.

لا يوجد source ولا created_at ولا updated_at.

{
"id": "6abe570b9ac75c8c65a5fa1a",
"location_name": "Docs capture",
"is_default": 0,
"formatted_address": "King Fahd Rd, Al Olaya, Riyadh 12211",
"area_name": "Olaya",
"street": "King Fahd Rd",
"city": "Riyadh",
"area": "Al Olaya",
"state": "",
"zipcode": "12211",
"country": "Saudi Arabia",
"country_code": "SA",
"lat": "24.7136",
"lng": "46.6753",
"image_urls": []
}

التُقط على dev، 2026-10-01 (العميل 356259): العنوان الذي أنشأته عينة create-address أدناه، وقُرئ مباشرة بعد إنشائه، وحُذف في نهاية الجولة. وكان نص العنوان توضيحيًا أصلًا.

عاد العنوان نفسه من create مع state: null، وهنا مع state: "": وهذا هو الفرق بين الشكلين.

الأخطاء​

HTTPBodyمتى
401{"status":401,"message":"Unauthorization"}لا token، أو token ليس JWT من Locate، أو عميل غير نشط، أو سجل عميل تعذّر تحميله.
404{"status":404,"message":"Address not found"}لا يوجد عنوان لهذا العميل يطابق المعرّف. ويشمل ذلك عنوانًا حُذف، ومعرّفًا يخص عميلًا آخر.

التُقط 404 على dev في 2026-10-01 بقراءة عنوان العينة بعد حذفه، وفي 2026-10-02 لـ ObjectId غير معروف. والمعرّف الذي يخص عميلًا آخر يحصل على الإجابة نفسها لأن البحث لا يفتش إلا في عناوين المستدعي (قراءة شيفرة؛ ولم يُجرَّب معرّف غريب مباشرة على Locate). وتجيب Shukah على معرّف شخص آخر بـ 403 بدلًا من ذلك (التُقط على dev، 2026-10-02؛ انظر الفروق عن Shukah). وعلى dev تحمل أجسام الأخطاء أيضًا حقل stack فيه stack trace للخادم كنص. وتتركه العينات في هذه الصفحة.

جرّبه​

export AUTH_BASE_URL=https://dev.authentication.locate.sa
export TOKEN='<locate-jwt>' # see "Getting a test token" on the module overview
export ADDRESS_ID='<id-from-the-list>'
curl -s "$AUTH_BASE_URL/api/v1/clients/address-book/$ADDRESS_ID" -H "Authorization: Bearer $TOKEN"

المتوقع: 200 والعنوان بشكل التفصيل. والمعرّف المجهول يعطي 404 المبيّن تحت «الأخطاء».

الفروق عن Shukah​

الجانبShukahLocateالأثر على التطبيق
URLGET $SHUKAH_BASE_URL/maeda/address-book/{id}GET $AUTH_BASE_URL/api/v1/clients/address-book/{id}غيّر base URL والمسار.
idعدد صحيح (التُقط على dev، 2026-10-01).سلسلة من 24 حرفًا. ومعرّف Shukah العددي ما زال يعمل في المسار للعناوين التي جاءت من دفتر عناوين Shukah.تُرجع القائمة الآن ObjectIds. ويقارن التطبيق معرّف آخر عنوان محدَّد مخزَّنًا لديه مع معرّفات القائمة كسلاسل، لذا فالعدد الصحيح المحفوظ من Shukah لم يعد يطابق ويُسقَط التحديد.
lat وlngأرقام JSON، مثل 24.7136 (التُقط على dev، 2026-10-01).سلاسل نصية، مثل "24.7136".لا شيء: فالتطبيق يقبل الاثنين ويحوّل بـ Number() قبل الاستخدام.
is_default0 أو 1. العنوان 162115 يساوي 0 (التُقط على dev، 2026-10-02).0 أو 1. والعنوان نفسه مقروءًا بمعرّفه في Shukah يساوي 1 (التُقط على dev، 2026-10-02).النوع واحد، والقيمة ليست كذلك: فقد يتغير العنوان الافتراضي الذي يعرضه التطبيق.
image_urlsمصفوفة أو null. للعنوان 162115 رابط صورة واحد (التُقط على dev، 2026-10-02).مصفوفة دائمًا. وللعنوان نفسه [].تضيع صورة عنوان منسوخ من Shukah.
مفتاح إضافيposition.لا شيء.لا شيء: فالتطبيق لا يقرؤه.
عنوان شخص آخر403 {"name":"Forbidden","message":"You can only view address that belong to you.","code":0,"status":403,"type":"Symfony\\Component\\HttpKernel\\Exception\\AccessDeniedHttpException"} (التُقط على dev، 2026-10-02، المعرّف 1).404 Address not found، مثل المعرّف المجهول (قراءة شيفرة).يتغير الـ status والنص الذي يعرضه التطبيق.
body الخاص بـ 404{"name":"Not Found","message":"Object not found: 162119","code":0,"status":404,"type":"Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException"} (التُقط على dev، 2026-10-01).{"status":404,"message":"Address not found"}يعرض التطبيق message، فيتغير النص الذي يعرضه.

POST /api/v1/clients/address-book​

يستبدل ShukahPOST /maeda/address-book✅ تم الاستبدال
يحتاج تعديل التطبيق3 breaking · 2 للمراقبة
  • 🔴 يحصل token من Shukah على 401 "Unauthorization"؛ أرسل JWT من Locate (من exchange-token؛ واحتفظ بـ token من Shukah).
  • 🔴 الاستجابة هي {status,address:{...}}؛ ويبني التطبيق الإعداد المسبق من المستوى الأعلى فتصبح id وlat/lng قيمة NaN.
  • 🔴 لا يوجد geocoding: تكون street وcity وarea وstate وzipcode وcountry وformatted_address قيمتها null (وتملؤها Shukah).
  • 🟡 قيمة address.is_default من نوع boolean (وفي Shukah 0)؛ وlat وlng أرقام هنا لكنهما سلسلتان نصيتان في get وupdate.
  • 🟡 لم يظهر العنوان المُنشأ على Locate في Shukah أبدًا (يستهدف الدفع /maeda/api/address-book الذي يعطي 404).

الطلب (Request)​

كل حقول الـ body اختيارية ولا يُتحقق من شيء. والمفاتيح غير المدرجة تُتجاهل. ويضبط الخادم source على locate والطوابع الزمنية على الآن، فلا يستطيع الـ body ضبطها.

الحقلالموضعالنوعمطلوبالقيودالوصف
AuthorizationheaderstringنعمBearer <locate-jwt>.الـ JWT من Locate.
location_name وstreet وarea وarea_name وcity وstate وzipcode وcountry وcountry_code وformatted_addressbodystringلاتُحذف المسافات الزائدة. والفارغ أو null يُخزَّن null. ولا حد للطول.أجزاء العنوان.
lat وlngbodynumber أو سلسلة رقميةلاnull و"" والقيم غير الرقمية تُخزَّن null. لا فحص للمدى.الإحداثيات.
image_urlsbodyarray of stringلاتُحذف المسافات الزائدة من السلاسل وتُسقَط الفارغة. وnull تعطي []. وتُقبل أيضًا سلسلة مصفوفة JSON أو سلسلة مفصولة بفواصل.عناوين URL للصور.
is_defaultbodyboolean أو 0 أو 1لافقط 1 و"1" وtrue تعني افتراضيًا. وكل قيمة أخرى، بما فيها "true" و2، تعني غير افتراضي.جعل هذا العنوان هو الافتراضي.

ما يرسله التطبيق في نسخة 2026-02-26 هو فقط location_name وarea_name وlat و lng (كلاهما سلسلة)، وis_default (0 أو 1) وimage_urls (مصفوفة أو null).

طلب استُخدم للالتقاط أدناه:

{
"location_name": "Docs capture",
"street": "King Fahd Rd",
"area": "Al Olaya",
"area_name": "Olaya",
"city": "Riyadh",
"zipcode": "12211",
"country": "Saudi Arabia",
"country_code": "SA",
"lat": 24.7136,
"lng": 46.6753,
"formatted_address": "King Fahd Rd, Al Olaya, Riyadh 12211",
"image_urls": [],
"is_default": false
}

الاستجابة (Response)​

200 مع غلاف يحمل العنوان الجديد بشكل القائمة:

الحقلالنوعيقبل nullالصيغة / القيودالوصف
statusintegerلادائمًا 200.صدى الحالة.
addressobjectلاشكل القائمة، بالحقول المدرجة تحت كتلة list. وsource هو locate. وis_default هو true عندما طلبه الطلب أو عندما لم يكن للعميل عنوان افتراضي.العنوان الذي أُنشئ.
{
"status": 200,
"address": {
"id": "6abe570b9ac75c8c65a5fa1a",
"source": "locate",
"is_default": false,
"location_name": "Docs capture",
"street": "King Fahd Rd",
"area": "Al Olaya",
"area_name": "Olaya",
"city": "Riyadh",
"state": null,
"zipcode": "12211",
"country": "Saudi Arabia",
"country_code": "SA",
"lat": 24.7136,
"lng": 46.6753,
"formatted_address": "King Fahd Rd, Al Olaya, Riyadh 12211",
"image_urls": [],
"created_at": "2026-10-01T12:50:19.661Z",
"updated_at": "2026-10-01T12:50:19.661Z"
}
}

التُقط على dev، 2026-10-01 (العميل 356259، كتابة مباشرة في Task 9). حُذف العنوان في نهاية الجولة. وكان نص العنوان توضيحيًا أصلًا. وis_default هو false لأن العميل كان لديه عناوين افتراضية بالفعل.

الأخطاء​

HTTPBodyمتى
401{"status":401,"message":"Unauthorization"}لا token، أو token ليس JWT من Locate، أو عميل غير نشط، أو سجل عميل تعذّر تحميله.
500على dev: {"status":500,"message":"<raw error text>","stack":"<stack trace>"}. وفي production: {"status":500,"message":"Internal server error"}.فشل غير متوقع، مثل حفظ يتعارض مع نسخة من بيانات العميل من Shukah تصل في اللحظة نفسها. لم يُلتقط. وعلى dev تكون الرسالة نص الخطأ الخام ويُضاف حقل stack؛ ولا تظهر Internal server error إلا في production (UAT وproduction: غير موثّق بعد).

لا يوجد 400: فالقيم السيئة تُنظَّف أو تُخزَّن null. والتُقط body الخاص بـ 401 على dev في 2026-10-01 دون token.

جرّبه​

ينشئ هذا الاستدعاء عنوانًا حقيقيًا على dev. احذفه بعد ذلك باستدعاء delete أدناه.

export AUTH_BASE_URL=https://dev.authentication.locate.sa
export TOKEN='<locate-jwt>' # see "Getting a test token" on the module overview
curl -s -X POST "$AUTH_BASE_URL/api/v1/clients/address-book" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{"location_name":"Docs test","area_name":"Olaya","lat":"24.7136","lng":"46.6753","is_default":0,"image_urls":[]}'

المتوقع: 200 و{"status":200,"address":{...}}. وهذا الـ body هو ما يرسله التطبيق، لذا تعود street وcity وarea وstate وzipcode وcountry وcountry_code وformatted_address بالقيمة null (التُقط على dev، 2026-10-02، بهذا الـ body تحديدًا). احتفظ بـ address.id للاستدعاءات الأخرى.

الفروق عن Shukah​

الجانبShukahLocateالأثر على التطبيق
URLPOST $SHUKAH_BASE_URL/maeda/address-bookPOST $AUTH_BASE_URL/api/v1/clients/address-bookغيّر base URL والمسار.
الاستجابةكائن العنوان نفسه، مسطّح (flat)، مع id عدد صحيح ومفتاح position (التُقط على dev، 2026-10-01).{"status":200,"address":{...}} مع id من 24 حرفًا.يقرأ التطبيق id وlat وlng وغيرها من المستوى الأعلى للإجابة. ومع الغلاف تكون كلها مفقودة، وتصبح الإحداثيات التي يبنيها للعنوان المحدَّد NaN. اقرأ address بدلًا من ذلك.
أجزاء العنوان المفقودةطلب فيه فقط lat وlng وarea_name وlocation_name وis_default وimage_urls عاد مع street وarea وstate وzipcode وcountry وcountry_code وformatted_address معبَّأة (التُقط على dev، 2026-10-01، ومرة أخرى في 2026-10-02 مع position 15). وكيف تشتقها Shukah: غير موثّق بعد.يخزّن فقط ما أُرسل. وأي شيء لم يُرسل هو null: فقد عاد الطلب نفسه والقيم الثماني كلها null (التُقط على dev، 2026-10-02).العنوان المنشأ بـ body التطبيق الحالي لا شارع ولا مدينة ولا عنوان منسَّق (formatted address) له. وشاشة الخريطة تملك هذه القيم، لذا يستطيع التطبيق إرسالها، أو يجب على الـ backend ملأها. وهل هذا مخطَّط له: غير موثّق بعد.
عنوان بالاسم نفسهيحذف التطبيق عنوانًا موجودًا بالاسم نفسه قبل أن ينشئ الجديد.يعمل الاستدعاءان نفسهما. ويستخدم delete المعرّف من القائمة، وهو سلسلة.لا شيء في هذه الخطوة. انظر كتلة delete لعملية الحذف الصريحة.
مكان تخزين العنوانفي Shukah.في Locate، ثم نسخة بذل أقصى جهد (best-effort) إلى Shukah.على dev لم تصل النسخة إلى Shukah: فقد ظلت قائمة Shukah تحتوي 13 عنوانًا بعد create وupdate وdelete في 2026-10-01، وفي 2026-10-02 لم يظهر العنوان المنشأ عبر Locate على Shukah أيضًا. ولا يُنسخ delete أبدًا. فلا يمكن افتراض أن عنوانًا أُنشئ عبر Locate موجود على Shukah.

PUT /api/v1/clients/address-book/:id​

يستبدل ShukahPUT /maeda/address-book/:id✅ تم الاستبدال
يحتاج تعديل التطبيق1 breaking · 5 للمراقبة
  • 🔴 يحصل token من Shukah على 401 "Unauthorization"؛ أرسل JWT من Locate (من exchange-token؛ واحتفظ بـ token من Shukah).
  • 🟡 id سلسلة hex من 24 حرفًا وlat وlng سلسلتان نصيتان؛ ويقرأ التطبيق المفاتيح نفسها فلا حاجة إلى تغيير.
  • 🟡 الأجزاء غير المعيّنة من العنوان تعود "" على Locate (city وarea وstate ...)؛ وتُرجع Shukah القيم المحدَّدة جغرافيًا.
  • 🟡 لا يصل التعديل الذي يُجرى على Shukah إلى Locate أبدًا ("S (edited)" بقي "Parity test S" هناك).
  • 🟡 تُبقي Locate عنوانًا افتراضيًا واحدًا بالضبط عند update؛ وأرجعت Shukah is_default بقيمة 0 دائمًا.
  • 🟡 يحمل body الـ 404 قيمة stack من الخادم على dev.

body مسطّح بنمط Shukah؛ ويمكن أن يكون المعرّف معرّف hex من 24 حرفًا أو معرّف Shukah العددي.

الطلب (Request)​

تحديث جزئي: لا يتغير سوى المفاتيح الموجودة في الـ body.

الحقلالموضعالنوعمطلوبالقيودالوصف
AuthorizationheaderstringنعمBearer <locate-jwt>.الـ JWT من Locate.
idpathstringنعمأرقام فقط: معرّف عنوان Shukah أولًا، ثم ObjectId. وأي شيء آخر: ObjectId فقط.العنوان المراد تغييره.
location_name وstreet وarea وarea_name وcity وstate وzipcode وcountry وcountry_code وformatted_addressbodystring أو nullلاالتنظيف نفسه كما في create. والمفتاح الموجود بالقيمة null أو "" أو مسافات يضبط الحقل على null.أجزاء العنوان.
lat وlngbodynumber أو سلسلة رقمية أو nullلاالتنظيف نفسه كما في create.الإحداثيات.
image_urlsbodyarray of string أو nullلاالتنظيف نفسه كما في create. وnull تعطي [].عناوين URL للصور.
is_defaultbodyboolean أو 0 أو 1لافقط 1 و"1" وtrue تعني افتراضيًا. انظر قواعد الافتراضي تحت «الميزة».جعل هذا العنوان هو الافتراضي أو عدمه.
source وcreated_at وأي مفتاح آخرbody—لايُتجاهل.—

ما يرسله التطبيق في نسخة 2026-02-26: location_name وarea وis_default (0 أو 1) وimage_urls.

{
"location_name": "Docs capture (edited)"
}

الاستجابة (Response)​

200 مع العنوان بشكل التفصيل، كما في get: دون غلاف، وis_default 0 أو 1، وlat وlng سلسلتان نصيتان.

{
"id": "6abe570b9ac75c8c65a5fa1a",
"location_name": "Docs capture (edited)",
"is_default": 0,
"formatted_address": "King Fahd Rd, Al Olaya, Riyadh 12211",
"area_name": "Olaya",
"street": "King Fahd Rd",
"city": "Riyadh",
"area": "Al Olaya",
"state": "",
"zipcode": "12211",
"country": "Saudi Arabia",
"country_code": "SA",
"lat": "24.7136",
"lng": "46.6753",
"image_urls": []
}

التُقط على dev، 2026-10-01 (العميل 356259، كتابة مباشرة في Task 9): الطلب أعلاه، أُرسل إلى عنوان عينة create. وكان نص العنوان توضيحيًا أصلًا.

الأخطاء​

HTTPBodyمتى
401{"status":401,"message":"Unauthorization"}لا token، أو token ليس JWT من Locate، أو عميل غير نشط، أو سجل عميل تعذّر تحميله.
404{"status":404,"message":"Address not found"}لا يوجد عنوان لهذا العميل يطابق المعرّف، بما في ذلك معرّف يخص عميلًا آخر.
500على dev: {"status":500,"message":"<raw error text>","stack":"<stack trace>"}. وفي production: {"status":500,"message":"Internal server error"}.فشل غير متوقع، كما في create. لم يُلتقط. وعلى dev تكون الرسالة نص الخطأ الخام ويُضاف حقل stack؛ ولا تظهر Internal server error إلا في production (UAT وproduction: غير موثّق بعد).

لا يوجد 400. والتُقط body الخاص بـ 401 على dev في 2026-10-01 دون token. وbody الخاص بـ 404 هو الذي التُقط لـ get-address.

جرّبه​

يغيّر هذا الاستدعاء عنوانًا على dev. استخدم عنوانًا أنشأته للاختبار.

export AUTH_BASE_URL=https://dev.authentication.locate.sa
export TOKEN='<locate-jwt>' # see "Getting a test token" on the module overview
export ADDRESS_ID='<id-from-the-create-call>'
curl -s -X PUT "$AUTH_BASE_URL/api/v1/clients/address-book/$ADDRESS_ID" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{"location_name":"Office"}'

المتوقع: 200 والعنوان بشكل التفصيل مع location_name الجديد.

الفروق عن Shukah​

الجانبShukahLocateالأثر على التطبيق
URLPUT $SHUKAH_BASE_URL/maeda/address-book/{id}PUT $AUTH_BASE_URL/api/v1/clients/address-book/{id}غيّر base URL والمسار.
الاستجابةالعنوان، مسطّح، مع id عدد صحيح، وأرقام لـ lat وlng، ومفتاح position (التُقط على dev، 2026-10-01 و2026-10-02).العنوان، مسطّح، مع id من 24 حرفًا، وسلاسل نصية لـ lat وlng، ودون position. وأجزاء العنوان التي لم تُضبط قط تعود "" (التُقط على dev، 2026-10-02).لا شيء بالنسبة إلى المفاتيح التي يقرؤها التطبيق (تأكّد في 2026-10-02). فالتطبيق يبني عنوانه المحفوظ من مفاتيح المستوى الأعلى، وكلها موجودة.
قواعد الافتراضيغير موثّق بعد.القواعد الواردة تحت «الميزة».إذا كان التطبيق يعتمد على طريقة Shukah في اختيار العنوان الافتراضي، فقارن قبل التحوّل.
النسخ إلى Shukahلا ينطبق.تذهب نسخة بذل أقصى جهد من العنوان المعدَّل إلى Shukah. وعندما لا يكون للعنوان معرّف في Shukah، تنشئ النسخة عنوانًا جديدًا هناك، وقد يكرره.على dev لم تظهر النسخة في قائمة Shukah في 2026-10-01 ولا في 2026-10-02 (انظر create). وتعديل أُجري على Shukah لم يصل إلى Locate أيضًا (2026-10-02).

DELETE /api/v1/clients/address-book/:id​

يستبدل ShukahDELETE /maeda/address-book/:id✅ تم الاستبدال
يحتاج تعديل التطبيق2 breaking · 2 للمراقبة
  • 🔴 يحصل token من Shukah على 401 "Unauthorization"؛ أرسل JWT من Locate (من exchange-token؛ واحتفظ بـ token من Shukah).
  • 🔴 يرسل التطبيق +id، فيصبح المعرّف hex ذو 24 حرفًا NaN ويجيب الحذف بـ 404؛ وتقارن الـ slice أيضًا بـ +id.
  • 🟡 الاستجابة 200 {"status":200}؛ وتعطي Shukah 204 بلا body؛ ويتجاهل التطبيق الـ body.
  • 🟡 لا يُدفع الحذف في Locate إلى Shukah، ولا يصل الحذف في Shukah إلى Locate (عناوين شبحية).

الطلب (Request)​

الحقلالموضعالنوعمطلوبالقيودالوصف
AuthorizationheaderstringنعمBearer <locate-jwt>.الـ JWT من Locate.
idpathstringنعمأرقام فقط: معرّف عنوان Shukah أولًا، ثم ObjectId. وأي شيء آخر: ObjectId فقط.العنوان المراد حذفه.

لا يوجد body.

الاستجابة (Response)​

200 مع مفتاح واحد:

الحقلالنوعيقبل nullالصيغة / القيودالوصف
statusintegerلادائمًا 200. ولا مفاتيح أخرى.صدى الحالة.
{
"status": 200
}

التُقط على dev، 2026-10-01 (العميل 356259، كتابة مباشرة في Task 9): حذف عنوان العينة.

الحذف نهائي. وإذا كان العنوان المحذوف هو الافتراضي وبقيت عناوين أخرى، يصبح أول عنوان بترتيب التخزين هو الافتراضي.

الأخطاء​

HTTPBodyمتى
401{"status":401,"message":"Unauthorization"}لا token، أو token ليس JWT من Locate، أو عميل غير نشط، أو سجل عميل تعذّر تحميله.
404{"status":404,"message":"Address not found"}لا يوجد عنوان لهذا العميل يطابق المعرّف. وحذف ثانٍ للمعرّف نفسه يحصل على هذا أيضًا، فالاستدعاء ليس idempotent.
500على dev: {"status":500,"message":"<raw error text>","stack":"<stack trace>"}. وفي production: {"status":500,"message":"Internal server error"}.فشل غير متوقع. لم يُلتقط. وعلى dev تكون الرسالة نص الخطأ الخام ويُضاف حقل stack؛ ولا تظهر Internal server error إلا في production (UAT وproduction: غير موثّق بعد).

التُقط body الخاص بـ 401 على dev في 2026-10-01 دون token. وbody الخاص بـ 404 هو الذي التُقط لـ get-address بعد هذا الحذف.

جرّبه​

يحذف هذا الاستدعاء عنوانًا على dev. استخدم عنوانًا أنشأته للاختبار.

export AUTH_BASE_URL=https://dev.authentication.locate.sa
export TOKEN='<locate-jwt>' # see "Getting a test token" on the module overview
export ADDRESS_ID='<id-from-the-create-call>'
curl -s -X DELETE "$AUTH_BASE_URL/api/v1/clients/address-book/$ADDRESS_ID" -H "Authorization: Bearer $TOKEN"

المتوقع: 200 و{"status":200}. وتشغيله مجددًا يعطي 404 المبيّن تحت «الأخطاء».

الفروق عن Shukah​

الجانبShukahLocateالأثر على التطبيق
URLDELETE $SHUKAH_BASE_URL/maeda/address-book/{id}DELETE $AUTH_BASE_URL/api/v1/clients/address-book/{id}غيّر base URL والمسار.
إجابة النجاح204 مع body فارغ (التُقط على dev، 2026-10-01).200 مع {"status":200}.لا شيء: فالتطبيق لا يقرأ الـ body.
المعرّف الذي يرسله التطبيقيحوّل التطبيق المعرّف إلى رقم بعلامة الجمع الأحادية (unary plus) قبل الاستدعاء. وهذا يعمل مع الأعداد الصحيحة في Shukah.يصبح المعرّف المكوَّن من 24 حرفًا NaN، فيستدعي التطبيق .../address-book/NaN. وهذا ليس أرقامًا فقط، فتبحث الخدمة عن ObjectId هو NaN وتجيب 404 Address not found (قراءة شيفرة، لم يُجرَّب مباشرة).يفشل الحذف الصريح في شاشة تعديل العنوان إلى أن يتوقف التطبيق عن تحويل المعرّف. أما حذف عنوان بالاسم نفسه داخل create فلا يحوّله.
body الخاص بـ 404{"name":"Not Found","message":"Object not found: 162119",...} (التُقط على dev، 2026-10-01).{"status":404,"message":"Address not found"}يعرض التطبيق message، فيتغير النص الذي يعرضه.
النسخ إلى Shukahلا ينطبق.لا يُنسخ الحذف إلى Shukah أبدًا.العنوان الذي أُنشئ أو عُدّل عبر Locate ثم حُذف عبر Locate قد يبقى على Shukah.

تنبيه​

  • يحوّل التطبيق معرّف العنوان إلى رقم قبل أن يحذف، فيصبح معرّف Locate (24 حرف hex) NaN ويفشل الحذف بـ 404.
  • يجيب Create بـ {status, address} بدل العنوان نفسه، ولا يملأ الشارع أو المدينة أو العنوان المنسَّق من الإحداثيات كما تفعل Shukah.
  • يُرجع List وcreate قيمًا منطقية وأرقامًا، ويُرجع get وupdate 0/1 وإحداثيات نصية، وقد تحتوي القائمة عدة عناوين افتراضية.

التفاصيل (للـ backend)​

فُحص dev فقط: الـ host https://dev.authentication.locate.sa والبادئة /api/v1. أما الـ host والبادئة في UAT وproduction: غير موثّق بعد. تحمل أجسام الأخطاء على dev حقل stack (التُقط في 2026-10-01 على 404 الخاص بـ get-address وعلى 400 الخاصة بـ profile وsetting)، لذا فإن dev لا يعمل بـ NODE_ENV=production؛ والـ handler لا يضيف stack إلا خارج production (src/middlewares/error-handler.js:12-35). ويجعل الـ handler نفسه 500 غير المتوقع يحمل نص الخطأ الخام وstack على dev، وInternal server error في production فقط (src/middlewares/error-handler.js:28-33).

البحث عن المعرّف​

تحوّل findAddressIndexByApiId معرّف المسار إلى نص. فإذا طابق ^\d+$ بحثت عن عنوان قيمة shukah_address_id فيه تساوي ذلك العدد، وإن لم يطابق أي عنوان رجعت إلى _id في الوثيقة الفرعية (src/controllers/client/address-book/lookup.js:13-25). ويستخدمها get وupdate وdelete جميعًا. ويجري البحث على مصفوفة addresses الخاصة بالمستدعي، ولهذا يعطي معرّف عميل آخر 404 (src/controllers/client/address-book/get.js:11-14؛ وتسرد وثيقة الخدمة 404 نفسه لمعرّف ليس للمستخدم الحالي، docs/api/client-auth-and-address-book.md:259-263). ويُنسخ معرّف Shukah من mt_address_book.id للعناوين التي جاءت من دفتر عناوين Shukah، وهو null للعناوين المنشأة عبر الـ API وللعنوان المضمَّن (inline) المبني من صف العميل (src/models/client.js:19، src/sync/mappers/client-mapper.js:32-47,50-53).

قواعد الكتابة​

  • يقرأ Create المفاتيح الواردة في جدول طلبه فقط، لذا تُتجاهل المفاتيح المجهولة وsource وshukah_address_id والطوابع الزمنية في الـ body. ويضبط source: 'locate' وshukah_address_id: null والطابعين الزمنيين على الآن (src/controllers/client/address-book/parse-payload.js:4-21، src/controllers/client/address-book/create.js:13,18).
  • دوال التحويل (casts): تحذف toStr المسافات الزائدة وتحوّل الفارغ أو null إلى null؛ وتعطي toNum القيمة null لـ null و"" والأعداد غير المنتهية (non-finite)؛ وtoBool تعطي true فقط لـ 1 و"1" وtrue؛ وتقبل toImageUrls مصفوفة أو سلسلة مصفوفة JSON أو سلسلة مفصولة بفواصل، وتحذف المسافات الزائدة وتُسقط الفارغ (src/sync/lib/casts.js:1,56-81).
  • يطبّق Update المفتاح فقط عندما يحتويه الـ body (hasOwnProperty)، لذا فإن null الموجودة تمسح الحقل (src/controllers/client/address-book/parse-payload.js:39-57). ولا يشغّل قاعدة الافتراضي إلا عندما يحتوي الـ body على is_default (src/controllers/client/address-book/update.js:22-24، src/controllers/client/address-book/parse-payload.js:60-75).
  • قاعدة الافتراضي في Create موجودة في resolveDefaultOnCreate (src/controllers/client/address-book/parse-payload.js:24-37)، وقاعدة Delete في resolveDefaultOnDelete، التي ترقّي addresses[0] (parse-payload.js:78-82، src/controllers/client/address-book/remove.js:15-17).
  • تعيد الـ handlers تحميل العميل دون query cache، لذا لا تستخدم أي قراءة أو كتابة النسخة المخزَّنة مؤقتًا لمدة 300 ثانية (src/controllers/client/address-book/load-fresh-client.js:7-8).
  • قد يفشل حفظ يتسابق مع تغيير وارد من Shukah بـ VersionError من Mongoose ويعطي 500 (قراءة شيفرة؛ فالدفع الوارد يرفع إصدار الوثيقة عن قصد، docs/plans/2026-07-13-shukah-address-push-api.md:58-59).

الأشكال (Shapes)​

تأتي إجابتا list وcreate من formatAddressForResponse، التي تستخدم ?? null للنصوص و Boolean(is_default) (src/controllers/client/address-book/mapper.js:4-28). وتأتي إجابتا get وupdate من formatAddressDetailForResponse، التي تحوّل كل نص مفقود إلى "" وis_default إلى 0 أو 1 وlat وlng إلى نص (src/controllers/client/address-book/mapper.js:30-51). والقائمة مرتبة بـ created_at الأحدث أولًا، والعناوين التي بلا تاريخ أخيرًا (src/controllers/client/address-book/handler.js:9-15).

العناوين الافتراضية في البيانات​

قاعدة «عنوان افتراضي واحد» تُفرض فقط عبر هذه الاستدعاءات الثلاثة من التطبيق. فيختار الـ ETL عنوانًا افتراضيًا واحدًا لكل عميل عندما يبني الوثيقة (src/sync/mappers/client-mapper.js:80-87)، لكن الدفع الوارد للعناوين من Shukah إلى Locate لا يجري أي انتخاب (src/controllers/admin/client-addresses/handler.js:67-68). وهكذا قد تكون كل العناصر العشرة الملتقطة في القائمة افتراضية (2026-10-01)، وكذلك 28 من 30 (2026-10-02). وفي 2026-10-02 وصلت نسخة عنوان أُنشئ على Shukah وفيها is_default بقيمة true، مع أن Shukah أرسلت 0 (السبب: غير موثّق بعد). ولا تزال وثيقة الخدمة تقول إن الخادم يُبقي دائمًا عنوانًا افتراضيًا واحدًا بالضبط (docs/api/client-auth-and-address-book.md:291).

الدفع إلى Shukah​

بعد الحفظ المحلي، يدفع create وupdate العنوان إلى Shukah، بذل أقصى جهد ويُنتظر إتمامه. ويخزّن Create المعرّف المُرجَع بوصفه shukah_address_id. ويدفع Update إلى {shukah_address_id} عندما يكون للعنوان واحد، وإلا يرجع إلى دفع create. ولا يُدفع Delete (src/services/shukah-sync.js:238-415؛ docs/plans/2026-09-22-shukah-address-outbound-push.md:106-110,149-151). ولا يفعل الدفع شيئًا عندما تكون المزامنة معطّلة أو لا يكون الـ host أو token المسؤول مضبوطًا. وهل هو مفعّل على dev: غير موثّق بعد. وتوحي التقاطات 2026-10-01 بأنه لم يكن يعمل لهذا العميل: فبعد create وupdate وdelete في Locate، ظلت قائمة Shukah تحتوي 13 عنوانًا، بينما كان create منسوخ دون delete منسوخ سيترك 14.

وفي 2026-10-02 وُجد السبب في الشيفرة: يرسل دفع create إلى /maeda/api/address-book (src/services/shukah-sync.js:310)، وتجيب عليه Shukah على dev بـ 404؛ بينما تخدم Shukah /maeda/address-book. ويُبتلع الفشل ولا يُكتب إلا في sync_logs (:335). أما دفع update فيستخدم /maeda/address-book/{id} (:356) لكن فقط لعنوان له معرّف في Shukah بالفعل؛ وغيره يرجع إلى create المعطوب. والاتجاه الآخر معطوب أيضًا: فقد وصل create من Shukah إلى Locate خلال ثوانٍ، لكن update وdelete من Shukah لم يصلا أبدًا. ولدى Locate المستقبِلات (src/routes/admin.js:52-54)، فنسخة Laravel من Shukah لا تستدعيها (استنتاج). كما فقدت Locate روابط الصور للعناوين الأربعة من Shukah التي لها صورة؛ ويعالج toImageUrls المصفوفات وسلاسل JSON (src/sync/lib/casts.js:67-81)، فالفقد يحدث قبله في المصدر. السبب: غير موثّق بعد.

حيث تختلف الوثائق عن الشيفرة (القول للشيفرة)​

  • تقول وثيقة الخدمة إن source العنوان هو "locate" أو "shukah" (docs/api/client-auth-and-address-book.md:224). ويسمح النموذج بـ mt_client_inline وmt_address_book وlocate (src/models/client.js:18)، ويُظهر الالتقاط mt_address_book.
  • تقول وثيقة الخدمة إن الخادم يضمن عنوانًا افتراضيًا واحدًا بالضبط (docs/api/client-auth-and-address-book.md:291). وهذا يصح على استدعاءات التطبيق فقط، كما سبق.
  • تقول وثيقة تصميم مبكرة إن get يُرجع {status, address} (docs/plans/2026-07-07-shukah-address-book-api-local.md:13-14)، ثم تصححه إلى كائن مسطّح في الأسطر 23-24. والشيفرة تُرجع الكائن المسطّح.
  • تكتب وثائق التصميم مسارات Shukah بالشكل /maeda/api/address-book (docs/plans/2026-07-07-shukah-address-book-api-local.md:49). أما التطبيق فيستدعي /maeda/address-book، وتجيب Shukah على dev بـ 404 للصيغة ذات /api/، لذا تستخدم الصفحات مسار التطبيق.
  • تُظهر الالتقاطات المنقَّحة أن Shukah تُرجع lat وlng كأرقام، بينما يعلن نوع التطبيق نفسه أنهما سلسلتان (src/entities/location/model/types/location.server.ts:3-19).
  • 2026-10-02: أعطت هذه الصفحة 13 عنوانًا على Shukah و28 على Locate، ولا عنوان افتراضيًا على Shukah وكل العناصر العشرة افتراضية على Locate، وترتيبًا غير معروف على Shukah. وتُظهر التقاطات 2026-10-02 العددين 15 و30، وقيمة 0 على Shukah في الـ15 كلها، وقيمة true على Locate في 28 من 30، وترتيب Shukah حسب position.
  • 2026-10-02: توقعت هذه الصفحة ألا يكون هناك فرق في image_urls في list وget. وقد فقدت Locate روابط الصور للعناوين الأربعة من Shukah التي لها صورة.
  • 2026-10-02: ذكرت هذه الصفحة أن is_default في get واحد على الجانبين. والعنوان نفسه يساوي 0 على Shukah و1 على Locate.
  • 2026-10-02: قالت هذه الصفحة إن المعرّف الغريب يحصل على الإجابة نفسها على الجانبين. تجيب Shukah بـ 403؛ وتجيب Locate بـ 404 (قراءة شيفرة).
  • 2026-10-02: قالت هذه الصفحة إن أجزاء العنوان null في create كانت قراءة شيفرة. وقد التُقطت الآن.
  • 2026-10-02: «النسخة بذل أقصى جهد إلى Shukah» في create وupdate موجودة في الشيفرة (src/controllers/client/address-book/create.js:23، src/controllers/client/address-book/update.js:31)، لكن لم تصل أي نسخة إلى Shukah على dev في 2026-10-02 أيضًا (انظر الدفع إلى Shukah).

Sources​

  • locate-authentication-service@6757aa4: src/routes/client.js:17-21، src/controllers/client/address-book/handler.js:6-17، src/controllers/client/address-book/get.js:9-22، src/controllers/client/address-book/create.js:10-28، src/controllers/client/address-book/update.js:12-37، src/controllers/client/address-book/remove.js:8-21، src/controllers/client/address-book/lookup.js:13-25، src/controllers/client/address-book/load-fresh-client.js:7-8، src/controllers/client/address-book/mapper.js:4-51، src/controllers/client/address-book/parse-payload.js:4-82, src/sync/lib/casts.js:1,56-81، src/models/client.js:16-34, src/middlewares/error-handler.js:12-35، src/sync/mappers/client-mapper.js:32-87، src/controllers/admin/client-addresses/handler.js:67-68, src/services/shukah-sync.js:238-415
  • وثائق locate-authentication-service@6757aa4: docs/api/client-auth-and-address-book.md §4 إلى §8 (الأسطر 187-370، 224، 259-263، 291؛ آخر تغيير 2026-07-27)، docs/plans/2026-07-07-shukah-address-book-api-local.md:13-24,49,226، docs/plans/2026-07-13-shukah-address-push-api.md:58-59، docs/plans/2026-09-22-shukah-address-outbound-push.md:106-110,149-151
  • نسخة الجوال اللحظية mobile/locate-client@e960c3a (الفرع development، 2026-02-26؛ شيفرة التطبيق نفسه، وليست من Locate): src/entities/location/model/api/services/location.service.ts:21-24,37-41,55-59,73-78,92-96، src/entities/location/model/api/controllers/location.controller.ts:38-110، src/entities/location/model/api/dto/location.dto.ts:38-86,105-126,144-199، src/entities/location/model/types/location.server.ts:3-19، src/entities/location/model/constants/location.ts:15-18، src/entities/location/model/helpers/locationPresetToSelectedAddress.ts:3-20، src/entities/location/model/services/fetchLocationPresets/fetchLocationPresets.ts:17، src/entities/location/model/services/fetchLocationPresetById/fetchLocationPresetById.ts:17-19، src/entities/location/model/services/createLocationPreset/createLocationPreset.ts:50-92، src/entities/location/model/services/updateLocationPreset/updateLocationPreset.ts:18-20، src/entities/location/model/services/deleteLocationPreset/deleteLocationPreset.ts:20-21، src/entities/location/model/services/initLocation/initLocation.ts:33-38,78، src/entities/location/model/slice/location.slice.ts:56-58، src/features/SavedLocationsList/ui/SavedLocationsList/SavedLocationsList.tsx:70، src/features/UserLocationInfo/ui/UserLocationInfo/UserLocationInfo.container.tsx:44-46، src/widgets/LocationDrawer/ui/LocationDrawer/LocationDrawer.tsx:42-44، src/features/MapDrawer/model/services/createLocationPreset/saveLocation.ts:69-80، src/widgets/Map/ui/Map/Map.tsx:105، src/features/EditSavedAddress/model/services/init.ts:13-17، src/features/EditSavedAddress/model/services/updatePreset.ts:62-70، src/features/EditSavedAddress/model/services/deletePreset.ts:19، src/shared/api/reqError.ts:52-62
  • locate-authentication-service@6757aa4، الدفع والمزامنة: src/services/shukah-sync.js:310,335,356، src/routes/admin.js:52-54، src/sync/lib/casts.js:67-81
  • التقاطات dev، 2026-10-02 (parity audit): addr-list-before--shukah وaddr-list-before--locate-jwt و address-book-get--shukah وaddress-book-get--locate-jwt وaddress-book-get-shukahid--shukah و address-book-get-shukahid--locate-jwt وaddress-book-get-unknown--shukah و address-book-get-unknown--locate-jwt وaddress-create--shukah وaddress-create--locate-jwt و address-update--shukah وaddress-update--locate-jwt وaddress-delete--shukah و address-delete--locate-jwt وaddr-list-after-create--shukah وaddr-list-after-update--shukah و addr-list-after-delete--shukah وaddr-list-after-delete--locate-jwt
  • التقاطات dev، 2026-10-01: locate-address-list وlocate-address-get وlocate-address-create و locate-address-get-created وlocate-address-update وlocate-address-delete و locate-address-get-deleted وlocate-address-list-after-shukah-writes وshukah-address-list و shukah-address-get وshukah-address-create وshukah-address-update وshukah-address-delete و shukah-address-get-deleted وshukah-address-list-after-locate-writes و probe-locate-address-list وprobe-locate-address-get وprobe-locate-address-create و probe-locate-address-update وprobe-locate-address-delete