كيف تخزن سجل لمنتج ولم تخزن الفاتورة بعد؟
#1
السلام عليكم و رحمة الله و بركاته
أولا أوصيكم و نفسي بما تبقى من العشر من ذي الحجة بالذكر فهي أفضل الأيام عند الله.

عند فتح فاتورة جديدة فرضا fac.append أكيد رايح تضع منتجات في هذه الفاتورة يعني facprod.append مع العلم أن الجدول fac هو ماستر للجدول facprod

السؤال : من سيخزن الاول ؟ أيهما تكتب الاولى fac.post أو facprod.post ؟
فإن كانت fac فهذا يعني أنو كل مرة ندخل منتج في الفاتورة تكون هناك fac.post و إن كانت facprod فهي مستحيلة لأن facprod لا تخزن قبل الماستر fac
الرد
#2
أظنني وجدت الحل و هو وضع خاصية lockType للجدول facprod تساوي ltBatchOptimistic
و في الحدث AfterPost الخاص بالجدول fac أضيف هذه التعليمة ;()facprod.UpdateBatch
فقط أنتظر تأكيد لكلامي..شكرا.
الرد
#3
وعليكم السلام
عمليات التحديث من اضافة وتعديل وحفظ تتم لكل جدول على حدا اي انه اذا اضفت فاتورة جديدة ولتكن رقم 02 للجدول masterفسواء قمت بعملية الحفظ ام لا فانك تستطيع اضافة منتج جديد للجدول detail
ماعدا الحذف ,ففي حال حذف الفاتورة باكملها فيتم ذلك ب sql او عن طريق حذف تسجيلة واحدة من جدول master ثم حلقة تحذف فيها جميع تسجيلات جدول detail بما يوافق جدول master
طبعا ستواجهك مشاكل اذا استعملت رقم الفاتورة هو masterfieldsخاصة اذا اردت تعديل رقم الفاتورة (فكر في هذا الامر)
الرد
#4
شكرا أخي على ردك

ظننت أني وجدت الحل و لكن تأتيني exception
و الرسالة هي row cannot be located for updating و تأتي مباشرة عندما أضغط على الزر موافق لحفظ الفاتورة(طبعا الفاتورة ليست فارغة يعني فيها منتجات).
الرد
#5
على ماأظن الخطا ناتج عن تعديل خصائص table
ارفق محاولتك
او مرفق لقاعدة البيانات فقط يتكون من 03 جداول produit.detail.mastr وستجد ضالتك ان شاء الله
حبذا لو تكون قاعدة البيانات absolute او paradox
الرد
#6
الاشكالية عندي هي كيف تضع post لـ facprod (الديتال) أثناء حجز المنتجات و الجدول fac (الماستر) لم تضع له post بعد
الرد
#7
السلام عليكم...

بما أنك تتعامل مع جدولين لهما علاقة ببعضهما فيجب وضع عمليات الحفظ (و غيرها) ضمن صفقة (Transaction) بحيث يتم الحفظ في كلا الجدولين أو تلغى العملية في كلا الجدولين معاً.

أتصور أن جدول التفاصيل (facprod) يحتوي على عمود أو حقل لرقم الفاتورة من الجدول الرئيسي (fac). بمعنى أن كل سجل سيحفظ في جدول التفاصيل سيحتاج إلى رقم الفاتورة أو السجل المرتبط به في الجدول الرئيسي.

إذا كان البرنامج على جهاز واحد (مستخدم واحد للبرنامج، و ليس على شبكة) فإن الأمر سهل:
1. احفظ بيانات الجدول الرئيسي.
2. باستعمال استعلام (Query) احصل على رقم الفتورة أو السجل الجديد الذي حفظته.
3. احفظ سجلات الجدول الفرعي (المنتجات).

المشكلة الوحيدة - و هي محلولة - هي أنه ربما لسبب ما تحفظ البيانات في الجدول الرئيسي ثم يحدث خطأ أو خلل قبل أت تحفظ سجلات التفاصيل! و الحل كما ذكرنا أعلاه يكمن في استخدام الـ Transaction:

* إذا كنت تستخدم مكونات BDE فيجب أن يرتبط كلا الجدولين بمكون TDatabase واحد، ثم نستخدم الوظيفة StartTransaction لفتح الصفقة (Transaction) ثم الوظيفة Commit لإنهاء الـ Transaction و حفظ البيانات في كلا الجدولين معا، أو الوظيفة Rollback لإنهاء الـ Transaction و إلغاء عملية الحفظ من كلا الجدولين معا في حالة حدوث خطأ.

* إذا كنت تستخدم مكونات ADO فيجب أن يرتبط كلا الجدولين بمكون TADOConnection واحد، ثم نستخدم الوظيفة BeginTrans لفتح الصفقة (Transaction) ثم الوظيفة CommitTrans لإنهاء الـ Transaction و حفظ البيانات في كلا الجدولين معا، أو الوظيفة RollbackTrans لإنهاء الـ Transaction و إلغاء عملية الحفظ من كلا الجدولين معا في حالة حدوث خطأ.

فيما يلي كود عام بالخطوات الأساسية:

كود :
var NewID: Integer; // ... try Database1.StartTransaction; // بداية الصفقة fac.Append; // ... // جمل تسجيل بيانات الجدول الرئيسي // ... fac.Post; // الحصول على رقم السجل الجديد Query1.SQL.Text := 'SELECT MAX(id_field) AS MaxID FROM fac_table'; Query1.Open; NewID := Query1.FieldByName('MaxID').AsInteger; // ربما هنا بداية حلقة أو ما شابه لتسجيل المنتجات facprod.Append; // ... // جمل تسجيل بيانات الجدول الفرعي // ... facprod.Post; // نهاية الحلقة if Database1.InTransaction then Database1.Commit; // اعتماد البيانات في كلا الجدولين و إنهاء الصفقة except if Database1.InTransaction then Database1.Rollback; // التراجع عن كل التغييرات في كلا الجدولين و إنهاء الصفقة ShowMessage('خطأ في حفظ البيانات'); end;

* طبعاً id_field هو اسم حقل المفتاح الأساسي في الجدول الرئيسي، و fac_table هو اسم الجدول الرئيسي في قاعدة البيانات.

نرجو الاستفادة و السلام.
الرد
#8
يااخي لا تحفظ كلا الجدولين معا بزر واحد سبق وان ذكرت في مشاركتي السابقةبالتعامل مع الجدولين كل على حدا
حل بسيط
بمجرد ان تضيف منتوج او تعدل عليه قم بحفظه مباشرة
على اعتبار ان dbgrid1 متصل ب: factproduit من الخاصية onkeyPress ل:dbgrid1
PHP كود :
begin
If key =#13 then
begin
factproduit
.edit;
factproduit.post;
end;
end; 

ثم احفظ fact بزر الحفظ وليكن button1
الرد
#9
لا أستطيع أن أحفظ المنتوج و الفاتورة لم تحفظ بعد لأن الفاتورة هي الماستر .

مع العلم أني تخليت عن الخاصية ltoptimisticbatch لأنه في الديبيغريد الخاص بالمنتج في كل مرة أضيف منتج بالضغط على زر الاتجاه للأسفل تختفي كل المنتجات.
الرد
#10
وعليكم السلام ورحمة الله
cosinuszero كتب :من سيخزن الاول ؟ أيهما تكتب الاولى fac.post أو facprod.post ؟
فإن كانت fac فهذا يعني أنو كل مرة ندخل منتج في الفاتورة تكون هناك fac.post
لم تذكر اي معلومات عن حقول الجدولين كي يمكن معرفة على اي منطق تبرمج
دائما اوضح نوع قاعدة البيانات، اصدار دلفي المستخدم...

نعود للسؤال، الحالات كثيرة احسنها ما قاله الاخ ناجي باستخدام Transaction
يمكن ايضا اتباع المنطق التالي
عند البداية تستخدم fac.append و facprod.append
تكتب معلومات الفاتورة والمنتج وتحفظهما بfac.post و facprod.post ؟
ثم اي منتج اخر يضاف بfac.edit و facprod.append
والحفظ كما سبق fac.post و facprod.post ؟

فرضا هناك حقول بجدول الفاتورة تكتب بالمرة الاولى فقط، و حقول اخرى يمكن تعديلها بعد كل اضافة منتج طبعا هذا راجع لمنطقك

منطق اخر : تستغني كليا عن حدول الفاتورة وتستخدم فقط جدول واحد تسميه جدول الحركات او جروج/بيع منتج ومنه يمكنك استخراج مواد فاتورة باستعلام

tarek.inf كتب :
PHP كود :
factproduit.edit;
factproduit.post; 
ما كتبه فوق غير منطقي
عندما تستدعي Edit ثم بعدها Post فهذا لن يغير شيئ
الرد


التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم