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

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

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

يرجى ملاحظة أن البدلات قد تختلف من مقدم رعاية أطفال لآخر. وهي مرتبطة بمقدم رعاية أطفال معين من خلال رتبته الوظيفية. على سبيل المثال، السيدة ماري جوفينال، التي تبلغ رتبتها الوظيفية 2 (جدول الموظفين)، يتقاضى أجرًا بالساعة قدره 2.1 يورو (جدول التعويضات).
4.2.2. التوليد
يتم توفير البرنامج النصي لإنشاء قاعدة البيانات [dbpam_hibernate.sql]:
![]() |
قم بإنشاء قاعدة البيانات [dbpam_hibernate] (وهذا هو اسم قاعدة البيانات التي يستخدمها خادم الويب/jSON) وتأكد من أن حساب root (بدون كلمة مرور) يمكنه الوصول إليها. يمكنك القيام بذلك على النحو التالي:
قم بتشغيل MySQL، ثم [PhpMyAdmin]:
![]() | ![]() |
- [1-2]: قم باستيراد البرنامج النصي [dbpam_hibernate.sql] ثم قم بتنفيذه؛
4.2.3. نمذجة قاعدة البيانات بلغة Java
يتم نمذجة عناصر الجداول [EMPLOYEES] و[ALLOWANCES] و[CONTRIBUTIONS] بواسطة الفئات التالية:
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) {
...
}
// getters and setters
....
}
- الأسطر 8–15: تتوافق هذه الحقول مع الأعمدة في جدول [EMPLOYEES]؛
- السطر 16: يتوافق حقل [indemniteId] مع عمود [INDEMNITE_ID]، وهو المفتاح الخارجي لجدول [EMPLOYEES]؛
- السطر 17: بدل الموظف. لا يتم ملء هذا الحقل دائمًا:
- لا يتم ملؤه عند طلب عنوان URL [/employees]،
- يتم ملؤه عند طلب عنوان URL [/salary]؛
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) {
...
}
// getters and setters
....
}
- الأسطر 8-14: الحقول تتوافق مع أعمدة جدول [INDEMNITES]؛
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) {
...
}
// getters and setters
...
}
- الأسطر 8-13: الحقول تتوافق مع أعمدة جدول [COTISATIONS]؛
4.3. خادم الويب / تثبيت JSON
![]() |
4.3.1. التثبيت
يتم توفير ملف Java الثنائي لخادم الويب/JSON:
![]() |
لبدء تشغيل خادم web/JSON، اتبع الخطوات التالية:
- قم بتشغيل نظام إدارة قواعد البيانات MySQL؛
- تأكد من وجود قاعدة البيانات [dbpam_hibernate]؛
- افتح نافذة موجه الأوامر؛
- انتقل إلى مجلد jar؛
- اكتب الأمر:
هذا يفترض أن الملف القابل للتنفيذ [java.exe] موجود في مسار PATH بجهازك. إذا لم يكن الأمر كذلك، اكتب المسار الكامل لـ [java.exe]، على سبيل المثال:
يتم عرض السجلات:
- السطر 16: تم تحليل عنوان URL [/salary/{SS}/{ht}/{jt}]؛
- السطر 17: تم اكتشاف عنوان URL [/employees]؛
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) {
تقبل خدمة الويب عنواني URL التاليين:
- السطر 1: /employees: لاسترداد قائمة الموظفين؛
- السطر 4: /salary/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> {
// ----------------- properties
// operation status
private int status;
// any status messages
private List<String> messages;
// the body of the reply
private T body;
// manufacturers
public Response() {
}
public Response(int status, List<String> messages, T body) {
this.status = status;
this.messages = messages;
this.body = body;
}
// getters and setters
...
}
- يعيد عنوان URL [/employees] استجابة من نوع Response<List<Employee>>؛
- يعرض عنوان URL [/salary] نوع Response<PayStub>؛
فئة [PayrollSheet] هي كما يلي:
package pam.entities;
import java.io.Serializable;
public class FeuilleSalaire implements Serializable {
private static final long serialVersionUID = 1L;
// private fields
private Employe employe;
private Cotisation cotisation;
private ElementsSalaire elementsSalaire;
// manufacturers
public FeuilleSalaire() {
}
public FeuilleSalaire(Employe employe, Cotisation cotisation, ElementsSalaire elementsSalaire) {
...
}
// getters and setters
...
}
- السطر 9: تم تقديم فئة [Employee] في القسم 4.2.3؛
- السطر 10: تم تقديم فئة [Contribution] في القسم 4.2.3؛
فيما يلي فئة [SalaryElements] (السطر 11):
package pam.entities;
import java.io.Serializable;
public class ElementsSalaire implements Serializable {
private static final long serialVersionUID = 1L;
// private fields
private double salaireBase;
private double cotisationsSociales;
private double indemnitesEntretien;
private double indemnitesRepas;
private double salaireNet;
// manufacturers
public ElementsSalaire() {
}
public ElementsSalaire(double salaireBase, double cotisationsSociales, double indemnitesEntretien, double indemnitesRepas, double salaireNet) {
...
}
// getters and setters
...
}
4.4. اختبارات عميل Android
![]() |
فيما يلي الملف الثنائي القابل للتنفيذ لعميل Android النهائي:
![]() |
استخدم الماوس لسحب ملف [pam-client.apk] الموجود أعلاه إلى محاكي الجهاز اللوحي [GenyMotion]. سيتم بعد ذلك حفظه وتشغيله. قم أيضًا بتشغيل خادم الويب/JSON إذا لم تكن قد قمت بذلك بعد. الغرض من عميل Android هو استرداد المعلومات التي يعيدها خادم الويب/JSON وتنسيقها. فيما يلي طرق العرض المختلفة لعميل Android:
أولاً، يجب عليك الاتصال بخدمة الويب / JSON:

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

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

- في [7]، نتائج المحاكاة؛
- في [8]، احفظه؛

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

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

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

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










