4. TP 1: الإدارة الأساسية لبيانات الراتب
4.1. Introduction
لتطبيق ما تمت دراسته سابقًا، نقترح الآن مشروعًا يتمثل في كتابة عميل Android للأجهزة اللوحية، يسمح بمحاكاة حسابات كشوف رواتب موظفي إحدى الجمعيات.
سيكون للتطبيق بنية عميل/خادم:

- الخادم [1] متوفر؛
- يجب إنشاء عميل Android [2].
4.2. قاعدة البيانات
4.2.1. التعريف
سيتم وضع البيانات الثابتة المفيدة لإنشاء كشف الراتب في قاعدة بيانات سنسميها لاحقًا dbpam. تحتوي قاعدة البيانات هذه على الجداول التالية:
الهيكل:
المفتاح الأساسي | |
رقم الإصدار – يزداد مع كل تعديل في السطر | |
رقم الضمان الاجتماعي للموظف – فريد | |
اسم الموظف | |
اسمه الأول | |
عنوانه | |
مدينته | |
الرمز البريدي | |
مفتاح أجنبي في الحقل [ID] من الجدول [INDEMNITES] |
قد يكون محتواه كما يلي:

الهيكل:
المفتاح الأساسي | |
رقم الإصدار – يزداد مع كل تعديل في السطر | |
النسبة المئوية: الاشتراك الاجتماعي العام + الاشتراك في سداد الدين الاجتماعي | |
النسبة المئوية: الاشتراك الاجتماعي العام القابل للخصم | |
النسبة المئوية: الضمان الاجتماعي، الأرامل، الشيخوخة | |
النسبة المئوية: المعاش التكميلي + التأمين ضد البطالة |
قد يكون محتواه كما يلي:
![]()
معدلات الاشتراكات الاجتماعية مستقلة عن الموظف. الجدول السابق يحتوي على سطر واحد فقط.
المفتاح الأساسي | |
رقم الإصدار – يزداد مع كل تعديل للسطر | |
مؤشر المعالجة – فريد | |
السعر الصافي باليورو لساعة الحراسة | |
بدل الإعاشة باليورو لكل يوم رعاية | |
بدل الوجبات باليورو لكل يوم رعاية | |
بدل الإجازات المدفوعة الأجر. وهي نسبة مئوية تُطبق على الراتب الأساسي. |
قد يكون محتواها كما يلي:

تجدر الإشارة إلى أن البدلات قد تختلف من مربية أطفال إلى أخرى. فهي مرتبطة بمربية أطفال معينة من خلال مؤشر راتبها. وبالتالي، فإن السيدة ماري جوفينال التي لديها مؤشر راتب يبلغ 2 (الجدول EMPLOYES) تحصل على أجر ساعي قدره 2,1 يورو (الجدول INDEMNITES).
4.2.2. إنشاء
يتم توفير البرنامج النصي [dbpam_hibernate.sql] لإنشاء قاعدة البيانات:
![]() |
قم بإنشاء قاعدة البيانات [dbpam_hibernate] (هذا هو اسم BD الذي يستخدمه خادم الويب / jSON) وتأكد من أن تسجيل الدخول root بدون كلمة مرور يمكنه الوصول إليها. يمكنك القيام بذلك على النحو التالي:
قم بتشغيل MySQL ثم [PhpMyAdmin]:
![]() | ![]() |
- [1-2]: قم باستيراد البرنامج النصي [dbpam_hibernate.sql] ثم قم بتنفيذه؛
4.2.3. نمذجة قاعدة البيانات بلغة Java
يتم نمذجة عناصر الجداول [EMPLOYES] و [INDEMNITES] و [COTISATIONS] بواسطة الفئات التالية:
[Employe]
package pam.entities;
import java.io.Serializable;
public class Employe implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private int version;
private String SS;
private String nom;
private String prenom;
private String adresse;
private String ville;
private String codePostal;
private int idIndemnite;
private Indemnite indemnite;
public Employe() {
}
public Employe(String SS, String nom, String prenom, String adresse, String ville, String codePostal, Indemnite indemnite) {
...
}
// مُستردات ومُعيّنات
....
}
- السطور 8-15: تتوافق هذه الحقول مع أعمدة الجدول [EMPLOYES]؛
- السطر 16: الحقل [indemniteId] يتوافق مع العمود [INDEMNITE_ID] الذي يمثل المفتاح الخارجي للجدول [EMPLOYES]؛
- السطر 17: تعويض الموظف. لا يتم ملء هذا الحقل دائمًا:
- لا يتم ملؤه عند طلب URL [/employes]،
- ويكون مملوءًا عند طلب URL [/salaire]؛
[Indemnite]
package pam.entities;
import java.io.Serializable;
public class Indemnite implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private int version;
private int indice;
private double baseHeure;
private double entretienJour;
private double repasJour;
private double indemnitesCp;
public Indemnite() {
}
public Indemnite(int indice, double baseHeure, double entretienJour, double repasJour, double indemnitesCP) {
...
}
// الوصول والضبط
....
}
- السطور 8-14: الحقول تتوافق مع أعمدة الجدول [INDEMNITES]؛
[Cotisation]
package pam.entities;
import java.io.Serializable;
public class Cotisation implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private int version;
private double csgrds;
private double csgd;
private double secu;
private double retraite;
public Cotisation() {
}
public Cotisation(double csgrds, double csgd, double secu, double retraite) {
...
}
// الوصول والتعيين
...
}
- السطور 8-13: الحقول تتوافق مع أعمدة الجدول [COTISATIONS]؛
4.3. تثبيت خادم الويب / jSON
![]() |
4.3.1. التثبيت
يتم توفير ملف Java الثنائي لخادم الويب / jSON لك:
![]() |
لتشغيل خادم الويب / jSON، اتبع الخطوات التالية:
- قم بتشغيل SGBD MySQL ؛
- تأكد من وجود BD [dbpam_hibernate]؛
- افتح نافذة DOS؛
- انتقل إلى مجلد jar؛
- اكتب الأمر:
هذا يفترض أن الملف الثنائي [java.exe] موجود في PATH على جهازك. إذا لم يكن الأمر كذلك، اكتب المسار الكامل لـ [java.exe]، على سبيل المثال:
تظهر السجلات:
- السطر 16: تم اكتشاف URL [/salaire/{SS}/{ht}/{jt}]؛
- السطر 17: تم اكتشاف URL [/employes]؛
4.3.2. تم اكتشاف URL لخدمة الويب/jSON
![]() |
يتم تنفيذ خدمة الويب / jSON بواسطة Spring MVC وتعرض اثنين من URL:
@RequestMapping(value = "/employes", method = RequestMethod.GET, produces = "application/json; charset=UTF-8")
public EmployesResponse getEmployes() {
...
@RequestMapping(value = "/salaire/{SS}/{ht}/{jt}", method = RequestMethod.GET, produces = "application/json; charset=UTF-8")
public FeuilleSalaireResponse getFeuilleSalaire(@PathVariable("SS") String SS, @PathVariable("ht") double ht, @PathVariable("jt") int jt) {
تقبل خدمة الويب القيمتين التاليتين:
- السطر 1: /employes: للحصول على قائمة الموظفين؛
- السطر 4: /salaire/SS/ht/jt: للحصول على كشف راتب الموظف رقم [SS] الذي عمل [ht] ساعة خلال [jt] يومًا؛
فيما يلي لقطات شاشة توضح ذلك.
يُطلب من الموظفين:

نقوم بقطع الاتصال بالقاعدة، وإعادة تشغيل الخادم، ثم نطلب الموظفين:

نطلب راتبًا:

نطلب راتب شخص غير موجود:

4.3.3. الردود jSON من خدمة الويب/jSON
![]() |
![]() |
تقوم URL من خدمة الويب / jSON بإرسال ردود من النوع [Response<T>]:
package client.android.dao.service;
import java.util.List;
public class Response<T> {
// ----------------- الخصائص
// حالة العملية
private int status;
// رسائل الحالة المحتملة
private List<String> messages;
// نص الرد
private T body;
// المنشئات
public Response() {
}
public Response(int status, List<String> messages, T body) {
this.status = status;
this.messages = messages;
this.body = body;
}
// مُستردات ومُعيّنات
...
}
- تقوم URL [/employes] بإرجاع نوع Response<List<Employe>> ؛
- URL [/salaire] ترجع نوع Response<FeuilleSalaire> ;
الفئة [FeuilleSalaire] هي كما يلي:
package pam.entities;
import java.io.Serializable;
public class FeuilleSalaire implements Serializable {
private static final long serialVersionUID = 1L;
// الحقول الخاصة
private Employe employe;
private Cotisation cotisation;
private ElementsSalaire elementsSalaire;
// المنشئات
public FeuilleSalaire() {
}
public FeuilleSalaire(Employe employe, Cotisation cotisation, ElementsSalaire elementsSalaire) {
...
}
// الوصول والتعيين
...
}
- السطر 9: تم عرض الفئة [Employe] في الفقرة 4.2.3؛
- السطر 10: تم عرض الفئة [Cotisation] في الفقرة 4.2.3؛
الفئة [ElementsSalaire] (السطر 11) هي كما يلي:
package pam.entities;
import java.io.Serializable;
public class ElementsSalaire implements Serializable {
private static final long serialVersionUID = 1L;
// الحقول الخاصة
private double salaireBase;
private double cotisationsSociales;
private double indemnitesEntretien;
private double indemnitesRepas;
private double salaireNet;
// المنشئات
public ElementsSalaire() {
}
public ElementsSalaire(double salaireBase, double cotisationsSociales, double indemnitesEntretien, double indemnitesRepas, double salaireNet) {
...
}
// مُستردات ومُعيّنات
...
}
4.4. اختبارات عميل Android
![]() |
فيما يلي الملف الثنائي القابل للتنفيذ للعميل Android النهائي:
![]() |
استخدم الماوس لوضع الملف الثنائي [pam-client.apk] أعلاه على محاكي جهاز لوحي [GenyMotion]. سيتم بعد ذلك تسجيله ثم تنفيذه. قم أيضًا بتشغيل خادم الويب / jSON إذا لم تكن قد قمت بذلك بالفعل. يهدف عميل Android إلى استرداد المعلومات التي يرسلها خادم الويب / jSON وتنسيقها. فيما يلي العروض المختلفة لعميل Android:
يجب أولاً الاتصال بخدمة الويب / jSON:

- في [1]، يتم تقديم URL لخدمة الويب / jSON. باستخدام المحاكي، أدخل أحد عناوين IP من PC (ولكن ليس 127.0.0.1). باستخدام جهاز لوحي، أدخل عنوان wifi لجهاز خادم الويب / jSON وقم بتعطيل جدار الحماية الخاص بجهاز الخادم إن كان موجودًا لأنه قد يحظر المكالمات الواردة؛
- في [2]، نقوم بالاتصال؛
ثم نصل إلى صفحة المحاكاة:

- في [3]، نختار موظفًا؛
- في [4]، نحدد عدد الساعات؛
- في [5]، نحدد عدد الأيام؛
- في [6]، نطلب إجراء المحاكاة؛
صفحة المحاكاة التي يتم الحصول عليها هي التالية:

- في [7]، المحاكاة التي تم الحصول عليها؛
- في [8]، يتم تسجيلها؛

- في [9]، قائمة المحاكاة؛
- في [10]، يتم حذف محاكاة؛

- إلى [11]، لم تعد هناك محاكاة؛
- في [12]، نعود إلى نموذج المحاكاة؛

- في [13]، نجد النموذج؛
- في [14]، نعود إلى صفحة التكوين؛

- في [15]، نعود إلى نموذج تسجيل الدخول الأولي.
4.5. المهمة المطلوبة
يتم تزويدك بهيكل العميل Android المقدم سابقًا. وقد تم إنشاؤه استنادًا إلى المشروع [client-android-skel] الموصوف في الفقرة 2.
![]() |
المشروع قابل للتنفيذ ويحتوي بالفعل على العروض اللازمة. ما عليك سوى إضافة بعض الأكواد حتى تقوم التطبيق بما يجب عليها القيام به. الإجراء الذي يجب اتباعه هو التالي:
- قم بتشغيل النسخة الكاملة لفهم العمل المطلوب؛
- قم بتشغيل النسخة المبسطة وادرس الكود الخاص بها. فهو يتوافق مع أساليب التصميم المستخدمة في الصفحات السابقة؛
- أضف الكود المفقود؛










