السلام عليكم و رحمة الله تعالى و بركاته : هذا الجزء رقم 07 أو الدرس السابع من مشروع انجاز برنامج
لتسيير المخزون و التسويق (GSM) .
اليوم إن شاء الله سنخطو شوطا كبيرا و هاما في مشروعنــا ، ما عليك أخي الحبيب إلا الجاهزية و التركيز و خطوة خطوة إن شاء الله نبدأ:
سيكون عملنا كله اليوم على الفورم الرئيسي FGSM :
أولا قم باضاقة حقل من نوع تاريخ (d) في الجدول vente تحت اسم Date .
-قم باعطا الخاصية ReadOnly القيمة True لكل من DBLookupCombobox1+2+3+4
- قم بحذف العناصر sCombobox1+sEdit3+sEdit4 .
- قم بوضع العنصر GroupBox1 من القائمة أو الصفحة Standard ، اجعل الكابشن لهذا الأخير هي ( Montant de Produit ) .
داخل أو فوق العنصر GroupBox1 ، ضع 3 من sEdit ، سوف تكون أسماؤها على التوالي :
sEdit3+sEdit4+sEdit5 . بعد ذلك ضع عنوان لكل sEdit بعنصر sLabel . يعني فوق الأولى ضع sLabel يأخذ الكابشن Total HT ، و الثانية اجعل لها 2 من sLabel الأولى TVA و الثانية %00 ، و أما الـ sEdit5 اجعل لها sLabel بكابشن Total_TTC .
- أخيرا قم بوضع (DBGrid+DBNavigator) و اربط هما مع الجدول 6 ، ثم ضع آخرين و اربطهما من الجدول 2 . و آخرين للجدول Produit . للتنبيه : سوف يتم لاحقا حذف هذه العناصر الستة ، فقط قمنا بوضعها هنا لكي نشاهد و نراقب نتائج العمل عليهما أثناء البرمجة بشكل مباشر.
نأتي للجانب البرمجي:
بعد أن نذهب إلى المكون MainMenu (نضغط عليه مرتين) ، ثم نحدد Parametrès de vente ثم TVA ثم 00% ، على هذا الأخير الذي يأحذ الكابشن %00 و الإسم N01 ، نقوم باعطاء القيمة True للخاصية Checked ، يعني نجعله افتراضيا مع بداية المشروع محددا بتلك العلامة (Checked أو Cocher).
نغلق العنصر MainMenu ، و نحدد نفس العنصر %00 من قائمة الفورم FGSM ،
نضغط عليه ليعطينا امكانية تحرير الكود سورس ثم نكتب :
كود :
N01.Checked:=true;
N71.Checked:=false;
N171.Checked:=false;
sLabel5.Caption:='00 %' ;
sEdit1.SetFocus;
sEdit2.SetFocus;
ثم على %7 نحرر
كود :
N01.Checked:=false;
N71.Checked:=true;
N171.Checked:=false;
sLabel5.Caption:='7 %' ;
sEdit1.SetFocus;
sEdit2.SetFocus;
أخيرا على %17 نحرر
كود :
N01.Checked:=false;
N71.Checked:=false;
N171.Checked:=true;
sLabel5.Caption:='17 %' ;
sEdit1.SetFocus;
sEdit2.SetFocus;
أولا sLabel5 للتنبيه هي الموجود على GroupBox1 و المتعلقة بــ Tva ، و التي تأخذ الكابشن %00 .
ماذا يعني هذا الكود ؟ يعني بعد تنفيد البرنامج يكون %00 محددا افتراضيا ، و عند الضغط على غيره تقوم بتحديده مع حذف اشارة التحديد على البقية ، هذا يعرف المستخدم أي قيمة ضريبة يجري بها عملية البيع لأن قيمة الضريبة مختلفة و تضاف لقيمة البيع كما هو معروف ، أما Setfocus هذا لتحديد أو الانتقال إلى sEdit و سنعرف الغاية من ذلك فيما يلي.
- الآن نحدد العنصر sEdit1 و نذهب إلى évenements و نضغط مرتين على الحدث Onchange و نحرر :
كود :
if (sEdit1.Text<>'') and (sEdit2.Text<>'') and (sEdit1.Text>=floattostr(0))
and (sEdit2.Text>=floattostr(0)) and (N01.Checked=true) then begin
sEdit3.Text:=floattostr(strtofloat(sEdit1.Text)*strtofloat(sEdit2.text));
sEdit4.Text:=floattostr(0);
sEdit5.Text:=floattostr(strtofloat(sEdit3.Text)+strtofloat(sEdit4.Text)) end
else if (sEdit1.Text<>'') and (sEdit2.Text<>'') and (sEdit1.Text>=floattostr(0))
and (sEdit2.Text>=floattostr(0)) and (N71.Checked=true) then begin
sEdit3.Text:=floattostr(strtofloat(sEdit1.Text)*strtofloat(sEdit2.text));
sEdit4.Text:=floattostr(strtofloat(sEdit3.Text)*0.07);
sEdit5.Text:=floattostr(strtofloat(sEdit3.Text)+strtofloat(sEdit4.Text)) end
else if (sEdit1.Text<>'') and (sEdit2.Text<>'') and (sEdit1.Text>=floattostr(0))
and (sEdit2.Text>=floattostr(0)) and (N171.Checked=true) then begin
sEdit3.Text:=floattostr(strtofloat(sEdit1.Text)*strtofloat(sEdit2.text));
sEdit4.Text:=floattostr(strtofloat(sEdit3.Text)*0.17);
sEdit5.Text:=floattostr(strtofloat(sEdit3.Text)+strtofloat(sEdit4.Text)) end;
نفس الكود نريده في الحدث OnEnter لتفادي عدم كتابته مرة أخرى فقط نقوم بنسخ أو كتابة العبارة : sEdit1Change في الحدث OnEnter ، يعني بمجرد الدخول أو تغيير قيمة sEdit1 سوف ينفد الكود الذي كتبناه.
ماذا يعني هذا الكود ؟ باختصار الغرض منه حساب القيمة الإجمالية و قيمة الضريبة و القيمة الإجمالي بكل الرسوم ، فقط قيدناه بمجموعة من الشروط ، مثلا شرط عدم كون sEdit2 خالية لأنه لا يمكن اجراء عملية الحساب على قيمة غير موجودة أصلا.
طيب إذا كانت توجد قيمة في sEdit2 و قمة بكتابة قيمة في sEdit1 و قمة بتغيير هذه الأخيرة سوف تلحظ تغيير الناتج من حين لآخر و عليه فإن الأمور على مايرام ، و لكن إذا قمت بتغيير قيمة sEdit2 فلا يوجد أي فرق و السبب واضخ لأننا لم نبرمج شيئا على هذا الأخير.
إذا لم يكن هناك أي فرق في الكود الذي حررناه فنحن سوف نتجنب تكرار المود و فقط كما قمنا سابقا ، نكتب sEdit1Change في الحدثين OnChange و OnEnter للعنصر sEdit2 و بذلك كل شيء تمام. لكننا سوف نضيف سطرا في نفس الحدثين للعنصر sEdit1 و وهو يختلف عن sEdit2 ، و على هذا قم باعادة كتابة (أو نسخ) الكود ، يعني قم بنفس ما قمنا به مع sEdit1 .
بعد ما قمنا به مع tva و قما قمنا به مع sEdit1+2 ، الآن سوف نعرج على أمر ثالث وهو أهم و يتمثل
برمجة عمل الأزرار.
نبدأ بالزر Nouveau Facture :
المستعمل للبرنامج ليقوم بعملية أو عمليات بيع ، سوف تكون ضمن فواتير و لكل فاتورة رقم مستقل و لا يتكرر ، يعني هو مجبر أولا بتحديد فاتورة جديدة عن طريق هذا الزر ، و بعد ذلك يقوم بعمليات البيع بتحديد Nouveau Produit من حين لآخر حسب حاجة الزبون ، يعني يريد الزبون مثلا 5 مواد و كل مادة بكمية معينة ، يقوم المستعمل للبرنامج من ضغط مرة واحدة على Nouveau Facture و بعد ذلك يستعمل 5 مرات الزر Nouveau Produit ، إذا أراد الزبون فاتورة أخرى أو جاء زبون آخر ، يضغط المستخدم على فاتورة جديدة فتأخذ الرقم الموالي و يقوم بنفس ما تقدم ، و هكذا.
إذن نضغط مرتين على Nouveau Facture و نحرر :
كود :
var x:real;
begin
if Table6.IsEmpty Then Begin Table6.Edit;
Table6.FieldValues['N_Facture']:='1' ; Table6.Post;
sLabel2.Caption:=table6.FieldValues['N_Facture'];
end else
If Not Table6.IsEmpty Then begin
Table6.Last;
if Not Table6.FieldByName('Date_Facture').IsNull
Then Begin
Table6.Last; X:= table6.FieldValues['N_Facture'];
Table6.Insert; Table6.FieldValues['N_Facture']:=X+1; table6.Post;
sLabel2.Caption:=table6.FieldValues['N_Facture'];
End;
End;
sBitBtn1.Enabled:=false;
sBitBtn3.Enabled:=false;
sBitBtn4.Enabled:=false;
sBitBtn5.Enabled:=false;
sBitBtn6.Enabled:=false;
sBitBtn7.Enabled:=false;
sBitBtn8.Enabled:=false;
sBitBtn2.Enabled:=true;
end;
ماذا يعني هذا ؟
لدينا امكانية أن الجدول فارغا يعني أول استعمال ، و على هذا الشرط (الجدول فارغا_Empty) نقوم مباشرة بادخال أول رقم و هو 1 و نحفظ العملية.
لدينا امكانية أن الجدول ليس فارغا بينما حقل التاريخ فارغا ، أولا لماذا هذه الإمكانية؟ مثلا المستعمل يضغط فاتورة جديدة و لا يواصل العملية ، مثلا يغلق البرنامج أو يتوقف و يغلق الحاسوب ، و بعد فتح البرنامج مجددا ، و لولا هذا الشرط فإنه سوف يعمل رقم جديد موالي ، مع بقاء الرقم السابق محجوزا و لا يتضمن أي عملية بيع . على هذا الشرط أو هذه الحالة المتمثلة في عدم فراغ الجدول إضافة إلى عدم خلو حقل التاريخ من أي قيمة ، يقوم بالكود المطلوب ، و إلا فإنه لا يفعل أي شيء و بالتالي يتيح لك استخدام نفس الرقم للفاتورة التي توقفنا من العملية (سابقا) بعد تحديد رقمها.
و لماذا الشرط حول حقل التاريخ ؟ هذا الحقل أو غيره ، المهم أنه لن يكون خاليا بعد اجراء عملية البيع لأنه سيأخذ تاريخا معينا عند اتمام عملية البيع بالضغط على الزر Ajouter و سوف نرى كود سورس هذا الزر لاحقا.
و لماذا تعطيل بقية الأزرار ؟ لأن المستخدم لا يحتاجها في هذه الحالة ، و أيضا تركها مفعلة يمكن من الوقوع في الخلل ، إضافة إلى توجيه و تسهيل العملية على المستعمل فلن يذهب فكره بعيدا مع كثرة الأزرار و لن يتوه أو يضيع الوقت أو يخطئ.
الزر Nouveau Produit :
في حدث OnClick أو كالعادة نضغط مرتين على هذا الزر و نحرر:
كود :
if not Table6N_Facture.IsNull then begin
DbLookupCombobox1.ReadOnly:=False;
DbLookupCombobox2.ReadOnly:=False;
DbLookupCombobox3.ReadOnly:=False;
DbLookupCombobox4.ReadOnly:=False;
DateTimePicker1.DateTime:=now;
DbLookupCombobox2.DropDown;
sBitBtn2.Enabled:=False; // Nouveau Produit
sBitBtn3.Enabled:=true; // Ajouter
sBitBtn4.Enabled:=False; // Imprimer
sBitBtn5.Enabled:=False; // Suprimer
sBitBtn6.Enabled:=False; // Modifier
sBitBtn7.Enabled:=False; // Valider
sBitBtn8.Enabled:=true; // Anuler
sBitBtn9.Enabled:=False; // Suivant
sBitBtn10.Enabled:=False; // Précedent
sBitBtn11.Enabled:=False; // Début
sBitBtn12.Enabled:=False; // Fin
Filtrage1.Enabled:=false; // Fiche facture et Statistique
Vente1.Enabled:=false; // Fiche Vente
Table2.first;
table2.Insert; end else
showmessage('Priciser une Facture ou bien Nouveau Facture D''abord');
الزر Ajouter :
الآن الأمر مهم جدا ، و يتطلب التركيز، فقط للإشارة:
بعد تحديد Nouveau Facture ثم Nouveau Produit و ملئ كل الحقول بما في ذلك السعر و الكمية ، ستحفظ البيانات في الجدول Table2 يعني جدول Vente ، يتطلب الأمر تحيين (Mise ajour) للجدول Produit من حيث الكمية ، إذا كان لديك مثلا منتوج بكمية 100 في جدول المواد ، و قمت ببيع 10 فإنه حتما يتبقى 90 في جدول المواد ، و للقيام بالعملية يعني حفظ 10 بجدول البيع و طرح 10 من 100 ليكون الناتج90 بجدول المواد ثم الحفظ .
ثم في الكود قمنا باضافة شرط رائع و هام جدا يتمثل في تنبيه صاحب المحل أو المستعمل أن الكمية أوشكت على النفاد من المخزن في حال أصبحت الكمية تساوي أو تقل عن قيمة العتبة ، و يتمثل هذا في الحقل Seuil_Qut من جدول Produit ، يعني بعد كل عملية بيع يقارن الكمية المتبقية (الحقل Qut) مع العتبة (Seuil_Qut) لتظهر رسالة التنبيه أو لا.
كذلك شرط إجبارية ملء كل الحقول لتفادي الوقوع في مشاكل حسابية كثيرة ، في حالة وقع المستعمل سهوا أو خطأ في اجراء عملية بيع من دون اتمام ملئ كل الحقول.
إذن نحرر: