اذهب إلى المحتوى

لوحة المتصدرين

  1. باسل الشمري

    باسل الشمري

    الأعضاء


    • نقاط

      1

    • المساهمات

      1


  2. Mustafa Suleiman

    Mustafa Suleiman

    الأعضاء


    • نقاط

      1

    • المساهمات

      20334


  3. Sherif Aboghazala

    Sherif Aboghazala

    الأعضاء


    • نقاط

      1

    • المساهمات

      62


  4. محمد عاطف25

    محمد عاطف25

    الأعضاء


    • نقاط

      1

    • المساهمات

      9793


المحتوى الأكثر حصولًا على سمعة جيدة

المحتوى الأعلى تقييمًا في 01/20/26 في كل الموقع

  1. ارجو منكم المساعدة ولكم اشد الشكر والتقدير
    1 نقطة
  2. ليس هناك مشكلة يمكنك المتابعة مع الدورة هنا ونحن موجودون دائماً لمساعدتك في أي وقت .
    1 نقطة
  3. انا الان ادرس كورس js من عند الزيرو ويب سكول لأنه كامل واوشكت على الانتهاء منه هل انا قمت بخطوة افضل من دراسة js هنا
    1 نقطة
  4. منطق الكود الحالي غير مناسب للعمل في بيئة متعددة المستخدمين، فأنت تعتمد على توليد رقم الفاتورة وعرضه في TextBox قبل الحفظ، ولو فتح موظف ما شاشة البيع وحصل على رقم فاتورة 105، وفتح موظف آخر الشاشة في نفس اللحظة وحصل أيضاً على 105، فأول من يحفظ سينجح، والثاني سيحصل على خطأ Primary Key Violation أو سيقوم بتحديث فاتورة زميله حسب التصميم. لذا رقم الفاتورة يجب أن يولد لحظة الحفظ داخل قاعدة البيانات أو داخل الـ Transaction، ولا يؤخذ من الشاشة. كذلك استخدمت SqlDataAdapter لجلب كل الفواتير Select * ثم إضافة سطر واحد وحفظ الجدول بالكامل هو أسلوب يقتل سرعة البرنامج، فتخيل لو يوجد 100 ألف فاتورة، البرنامج سيقوم بتحميلها كلها للذاكرة فقط لإضافة فاتورة واحدة. الصحيح هو استخدام جملة INSERT INTO مباشرة عبر SqlCommand. وفي بيئة متعددة المستخدمين وحتى المستخدم الواحد، استخدام كائن اتصال static أو عام ومشارك، أمرخطير، فقد تتداخل الـ Transactions بين مستخدمين مختلفين إن لم يتم التعامل معها بحذر شديد. الصحيح هو إنشاء اتصال جديد new SqlConnection داخل جملة using لكل عملية حفظ. أيضًا قمت بالخصم من المخزون، لكن لو كانت الكمية المتبقية 5، وقام موظفان ببيع 3 قطع في نفس الثانية، فالكود الحالي سيسمح بذلك ويصبح الرصيد بالسالب (-1). وذكرت أنك تريد الاعتماد على حركة الصنف، لا مشكلة في ذلك، لكن من ناحية الأداء فلو أردت معرفة الرصيد الحالي، فلا يجب أن تقوم بجمع كل الحركات (مبيعات - مشتريات) من أول يوم للنظام في كل مرة تبيع فيها، لأن ذاك سيجعل النظام بطيئ مع الوقت. يجب أن تحتفظ بجدول Inventory به الرصيد الحالي لسرعة الاستعلام، وجدول ItemMovement لتسجيل التاريخ للتقارير والمراجعة، وقمت بذلك بالفعل لكن طريقة التنفيذ تحتاج تعديل، بحيث جدول Inventory يحتوي الرصيد الحالي اللحظي، ويتم التعديل عليه بالزيادة والنقصان لسرعة معرفة كم يوجد الآن؟ عند فتح فاتورة البيع. وجدول ItemDailyMovement هو سجل تاريخي لا يُحذف منه شيء، ولمعرفة رصيد الصنف بتاريخ قديم، أو مراجعة الحسابات، تقوم بجمع الحركات من ذلك الجدول. if (comboBox1.SelectedIndex == -1) { MessageBox.Show("الرجاء إدخال اسم زبون", "تنبيه", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } if (dataGridView4.Rows.Count == 0) { MessageBox.Show("الرجاء إدخال أصناف في الفاتورة", "تنبيه", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } decimal totalInvoice = 0; foreach (DataGridViewRow row in dataGridView4.Rows) { if (row.Cells[3].Value != null) totalInvoice += Convert.ToDecimal(row.Cells[3].Value); } textBox2.Text = totalInvoice.ToString("N2"); string totalAr = Class1.NumberToWords(Convert.ToDouble(textBox2.Text), "دينار ", "درهم"); using (SqlConnection con = new SqlConnection(Class1.sqlCon.ConnectionString)) { con.Open(); SqlTransaction trans = con.BeginTransaction(); try { string sqlInsertInvoice = @"INSERT INTO Invoices (invoice_date, customer_name, total_amount, total_ar) VALUES (@date, @cus, @total, @total_ar); SELECT SCOPE_IDENTITY();"; SqlCommand cmdInvoice = new SqlCommand(sqlInsertInvoice, con, trans); cmdInvoice.Parameters.AddWithValue("@date", dateTimePicker1.Value); cmdInvoice.Parameters.AddWithValue("@cus", comboBox1.Text); cmdInvoice.Parameters.AddWithValue("@total", totalInvoice); cmdInvoice.Parameters.AddWithValue("@total_ar", totalAr); object result = cmdInvoice.ExecuteScalar(); string newInvoiceID = result.ToString(); foreach (DataGridViewRow row in dataGridView4.Rows) { if (row.IsNewRow) continue; int itemId = Convert.ToInt32(row.Cells[5].Value); decimal qty = Convert.ToDecimal(row.Cells[1].Value); decimal price = Convert.ToDecimal(row.Cells[2].Value); decimal rowTotal = Convert.ToDecimal(row.Cells[3].Value); string itemName = row.Cells[0].Value.ToString(); string storeNum = row.Cells[4].Value.ToString(); string sqlDetails = @"INSERT INTO InvoiceDetails (invoice_number, item_name, item_id, inv_date, quantity, unit_price, total_price, store_number) VALUES (@invNo, @name, @id, @date, @qty, @price, @tot, @store)"; SqlCommand cmdDetails = new SqlCommand(sqlDetails, con, trans); cmdDetails.Parameters.AddWithValue("@invNo", newInvoiceID); cmdDetails.Parameters.AddWithValue("@name", itemName); cmdDetails.Parameters.AddWithValue("@id", itemId); cmdDetails.Parameters.AddWithValue("@date", dateTimePicker1.Value); cmdDetails.Parameters.AddWithValue("@qty", qty); cmdDetails.Parameters.AddWithValue("@price", price); cmdDetails.Parameters.AddWithValue("@tot", rowTotal); cmdDetails.Parameters.AddWithValue("@store", storeNum); cmdDetails.ExecuteNonQuery(); string sqlUpdateStock = @"UPDATE inventory SET quantity = quantity - @qty WHERE item_id = @id AND quantity >= @qty"; SqlCommand cmdStock = new SqlCommand(sqlUpdateStock, con, trans); cmdStock.Parameters.AddWithValue("@qty", qty); cmdStock.Parameters.AddWithValue("@id", itemId); int rowsAffected = cmdStock.ExecuteNonQuery(); if (rowsAffected == 0) { throw new Exception("الكمية غير متوفرة حالياً للصنف: " + itemName); } string dayName = dateTimePicker1.Value.ToString("dddd", new CultureInfo("ar-LY")); string sqlMove = @"INSERT INTO ItemDailyMovement (item_id, movement_date, day_name, quantity_sold, invoice_number, item_name, name_cus, type, invotry_num) VALUES (@id, @date, @day, @qty, @inv, @iname, @cus, 'مبيعات', @store)"; SqlCommand cmdMove = new SqlCommand(sqlMove, con, trans); cmdMove.Parameters.AddWithValue("@id", itemId); cmdMove.Parameters.AddWithValue("@date", dateTimePicker1.Value); cmdMove.Parameters.AddWithValue("@day", dayName); cmdMove.Parameters.AddWithValue("@qty", qty); cmdMove.Parameters.AddWithValue("@inv", newInvoiceID); cmdMove.Parameters.AddWithValue("@iname", itemName); cmdMove.Parameters.AddWithValue("@cus", comboBox1.Text); cmdMove.Parameters.AddWithValue("@store", storeNum); cmdMove.ExecuteNonQuery(); } Class1.OPER_CUSTOMERS(newInvoiceID, DateTime.Today, "مبيعات", totalInvoice, 0, comboBox1.Text, trans, label10.Text); trans.Commit(); MessageBox.Show("تم حفظ الفاتورة رقم " + newInvoiceID + " بنجاح", "تأكيد", MessageBoxButtons.OK, MessageBoxIcon.Information); fill_dgv3(); fill_dgv2_inv(); dataGridView4.Rows.Clear(); comboBox1.SelectedIndex = -1; textBox2.Clear(); label9.Text = ""; } catch (Exception ex) { trans.Rollback(); MessageBox.Show("فشل العملية: " + ex.Message, "خطأ", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
    1 نقطة
  5. وعليكم السلام ورحمة الله وبركاته. أولا لنجهز مشروع React للبناء من خلال الأمر : # في بيئة التطوير المحلية npm run build # أو yarn build وهكذا سيتم إنشاء مجلد build يحتوي على الملفات المجهزة والمجمعة. ثانيا رفع الملفات إلى الاستضافة : الطريقة الأولى وهي عبر cPanel قم بسجيل الدخول إلى cPanel الخاص بموقع dzsecurity.com ومن ثم انتقل إلى File Manager وافتح مجلد public_html أو المجلد الرئيسي لموقعك وقم برفع جميع محتويات مجلد build مباشرة إلى المجلد الرئيسي. أو الطريقة الثانية وهي من خلال FTP الخاص بموقعك وإستخدام برنامج مثل filezilla لرفع الملفات من خلاله. ثالثا تكوين خاص لموقع React : مثل ملف .htaccess للخوادم التي تدعم Apache وأنشئ ملف .htaccess في المجلد الرئيسي وأضف: Options -MultiViews RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.html [QSA,L] وإذا كان لديك دومين فرعيتأكد من رفع الملفات في المجلد الصحيح مثل subdomain.dzsecurity.com. رابعا إعدادات DNS والدومين : تأكد من توجيه الدومين إلى الخادم الصحيح وقد تحتاج لضبط إعدادات A Record أو CNAME لو كنت قد اشتريت النطاق domain بشكل منفصل
    1 نقطة
  6. وعليكم السلام ورحمة الله استضافة dzsecurity هي استضافة تقليدية (Shared Hosting)، وهذا النوع من الاستضافات لا يشغّل React مباشرة لأنه لا يدعم Node.js لتشغيل السيرفر، لكن يمكن رفع موقع React عليها بعد تحويله إلى ملفات ثابتة. الفكرة ببساطة أن React أثناء التطوير يعمل كسيرفر، أما عند النشر فنحن لا نرفع المشروع كاملًا، بل نرفع الناتج النهائي فقط. أول خطوة على جهازك هي بناء نسخة الإنتاج من المشروع. تدخل إلى مجلد مشروع React وتنفّذ أمر البناء. هذا الأمر يقوم بتحويل المشروع إلى HTML وCSS وJavaScript جاهزة للتشغيل على أي استضافة عادية. بعد الانتهاء سيظهر لديك مجلد جديد غالبًا اسمه build أو dist حسب الأداة المستخدمة. بعد ذلك تدخل إلى لوحة التحكم في استضافة dzsecurity، وغالبًا ستكون cPanel. من هناك تفتح مدير الملفات وتدخل إلى مجلد public_html، لأن هذا هو المجلد الذي تُعرض منه الملفات على المتصفح. إذا كان داخله ملفات قديمة يمكنك حذفها أو نقلها. الآن تقوم برفع محتويات مجلد build نفسه إلى داخل public_html، وليس المجلد كاملًا. المهم أن يكون ملف index.html موجودًا مباشرة داخل public_html. بعد رفع الملفات، افتح موقعك من المتصفح. في أغلب الحالات سيعمل مباشرة. إذا وجدت أن التنقل بين الصفحات لا يعمل ويظهر لك خطأ 404 عند تحديث الصفحة، فهذا بسبب أن React يعتمد على routing داخلي، والاستضافة لا تعرف ذلك. لحل هذه المشكلة تحتاج إلى إضافة ملف بسيط اسمه .htaccess داخل public_html. هذا الملف يخبر السيرفر أن أي رابط غير معروف يجب أن يعود إلى index.html، وبهذا يعمل الموقع بشكل طبيعي. أيضًا انتبه قبل البناء أن تضبط المسار الصحيح للموقع. إذا كان الموقع على الدومين الرئيسي فالأمر طبيعي، أما إذا كان داخل مجلد فرعي فيجب تعديل إعدادات React قبل البناء حتى لا تتكسر المسارات. باختصار، React لا يُرفع ككود تشغيل، بل يُرفع كناتج جاهز. طالما حصلت على ملفات HTML وJS النهائية، فهذه الاستضافة كافية تمامًا. إذا أردت لاحقًا موقع React مع Backend أو API، فستحتاج إما إلى استضافة تدعم Node.js أو فصل الواجهة الأمامية عن الخلفية كل واحد على استضافة مختلفة.
    1 نقطة
    ما رأيكم بنشر كتبكم في المكتبات لأن الكتب التعليمية تكون مطبوعة أفضل من أن تكون إلكترونية منها يستطيع أن يحدد أو يكتب ملاحظات على الكتاب، أفضل من القراءة فقط
    1 نقطة
×
×
  • أضف...