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

السؤال

نشر

 

انا اقوم في زر جديد عندما يضغط عليه مستخدم

بجلب اخر رقم من جدول هل  دالة مناسبة علما بانه مفتاح اساسي وترقيم تلقائي عمود id 

public static int CODE_GENE(string TABLE_NAME, string COLUMN_NAME)
{
    // استخدم استعلام MAX بدل جلب كل الصفوف
    int CODE = 0;
    using (SqlCommand cmd = new SqlCommand(
        $"SELECT ISNULL(MAX({COLUMN_NAME}),0) FROM {TABLE_NAME}", sqlCon))
    {
        if (sqlCon.State != System.Data.ConnectionState.Open)
            sqlCon.Open();

        CODE = Convert.ToInt32(cmd.ExecuteScalar());
    }
    return CODE;
}

علمًا بأنه لدي منطق حفظ فاتورة في حالة يعمل علي نظام أكثر من شخص بحيث يتم اصدار فاتورة أكثر من شخص في وقت واحد 

اعتماد رصيد صنف علي حركة صنف وليس تحديث مخزن بعد كل عملية بيع او تعديل فاتورة او فاتورة ترجيع 

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);
    }
}

 

Recommended Posts

  • 0
نشر

دالة CODE_GENE غير مناسبة في بيئة متعددة المستخدمين، فستؤدي لمشكلة أمنية، حيث المستخدم الأول يقرأ MAX(ID) = 100

والمستخدم الثاني يقرأ MAX(ID) = 100 أي نفس الرقم، ثم المستخدم الأول يحفظ فاتورة برقم 101، والمستخدم B يحفظ فاتورة برقم 101 أي يوجد تكرار.

كذلك أنت في كود الحفظ تستخدم SCOPE_IDENTITY() بالفعل وذلك هو الصحيح.

بالتالي لعرض رقم الفاتورة القادم فقط للعرض أي تقديري، فالرقم الفعلي للفاتورة يجب أن يأتي من SCOPE_IDENTITY() بعد الحفظ، قم بما يلي:

public static int CODE_GENE_SAFE(string TABLE_NAME, string COLUMN_NAME)
{
    int CODE = 0;
    using (SqlConnection con = new SqlConnection(sqlCon.ConnectionString))
    {
        con.Open();
        using (SqlCommand cmd = new SqlCommand(
            $"SELECT ISNULL(MAX([{COLUMN_NAME}]), 0) + 1 FROM [{TABLE_NAME}]", con))
        {
            CODE = Convert.ToInt32(cmd.ExecuteScalar());
        }
    }
    return CODE;
}

 

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...