一步一步学习Winform系列7:订单处理
1、 新订信息自动获取
2、 订单号递增
4、 新增订单明细
5、 清空订单明细
6、 确认提交订单
先看一下本功能模块的预览效果。
当用户要求生成新订单时,可以自动添加订单Id,并给订购客户combBox添加数据源,为订购日期自动添加默认时间。
点击新增产品按钮时,就弹出新增订单明细窗体进行设置。在这个窗体中可以自动根据产品的库存量设定是否可以销售。如果超过库存会进行提示。
提交确认时会提示本订单明细的信息,并自动加载到生成新订单中的Gridview中。
确认提交时也能进行提示。
自动获取客户信息和收货单位信息,并设置comboBox的相应事件
自动获取数据源跟之前新增雇员中部门表的获取是一样,请大家自行实现。
单击ComboBox进入后即可编辑SeletedIndexChanged事件,也就是当用户一点击改变了comboBox的选项,就自动填充相应信息到对应的文本框。。
//一旦订购客户选定了数据就绑定相应的文本框 private void cbx客户名称_SelectedIndexChanged(object sender, EventArgs e) { if (cbx客户名称.SelectedIndex != 0) { string strSQL = "SELECT * FROM 客户 WHERE 客户ID='" + cbx客户名称.SelectedValue + "'"; DataSet ds订购客户 = new DataSet(); ds订购客户 = SqlHelper.ExecuteDataset(SqlHelper.GetConnection(), CommandType.Text, strSQL); tbx客户地址.Text = ds订购客户.Tables[0].Rows[0]["地址"].ToString(); tbx客户城市.Text = ds订购客户.Tables[0].Rows[0]["城市"].ToString(); tbx客户邮编.Text = ds订购客户.Tables[0].Rows[0]["邮政编码"].ToString(); tbx客户国家.Text = ds订购客户.Tables[0].Rows[0]["国家"].ToString(); tbx客户地区.Text = ds订购客户.Tables[0].Rows[0]["地区"].ToString(); //默认情况下,收货单位与订购客户的信息是一致的,但是允许职工重新编辑收货信息 tbx收货单位.Text = ds订购客户.Tables[0].Rows[0]["公司名称"].ToString(); tbx收货地址.Text = ds订购客户.Tables[0].Rows[0]["地址"].ToString(); tbx收货城市.Text = ds订购客户.Tables[0].Rows[0]["城市"].ToString(); tbx收货邮编.Text = ds订购客户.Tables[0].Rows[0]["邮政编码"].ToString(); tbx收货国家.Text = ds订购客户.Tables[0].Rows[0]["国家"].ToString(); tbx收货地区.Text = ds订购客户.Tables[0].Rows[0]["地区"].ToString(); } }
为了方便后续编号的自动递增,在CommonFuc中添加一个公用方法。
#region 根据数据库表,自动递增主键编号 /// <summary> /// 先取得数据库内某个表最大的部门编号,递增1后作为新编号 /// </summary> /// <param name="strTable">数据库中的表格</param> /// <param name="strPKID">表的主键ID</param> /// <returns>新主键编号,用于显示在界面上</returns> public static int GetNewID(string strTable,string strPKID) { string strSQL = "SELECT " + strPKID + " FROM " + strTable + " ORDER BY " + strPKID + " DESC"; int Max编号 =Convert.ToInt32(SqlHelper.ExecuteScalar(SqlHelper.GetConnSting(), CommandType.Text, strSQL)); //给最大编号加1 return Max编号 + 1; } #endregion
在窗体加载事件中调用这个方法
datagridView控件会自动加载的是订单明细表,但是查看表结构我们发现:
我们发现订单明细表缺少一个单品总价的字段,不利于确认费用,因此在窗体加载时就添加一个新列,效果如图。
因此,需要自定义一个方法让datagridview绑定相应的数据源,进行单品总价的计算并填充到这个列。
完整的数据绑定代码如下:
//自定义方法:绑定datagridView的数据源 public void dataGridViewDatabing() { string strSQL = "SELECT * FROM 订单明细 WHERE 订单ID='" + tbx订单ID.Text + "'"; DataSet ds订单明细 = SqlHelper.ExecuteDataset(SqlHelper.GetConnection(), CommandType.Text, strSQL); grid生成新订单.DataSource = ds订单明细.Tables[0]; //如果还没有总价这一列,那么就添加新的一列 if (grid生成新订单.Columns.Count == 6) { //总价列可显示并且改变显示顺序 grid生成新订单.Columns["单品总价"].Visible = true; grid生成新订单.Columns["单品总价"].DisplayIndex = 5; //为总价一列赋值 for (int i = 0; i < ds订单明细.Tables[0].Rows.Count; i++) { double 总价 = Convert.ToDouble(grid生成新订单.Rows[i].Cells["单价"].Value) * Convert.ToInt32(grid生成新订单.Rows[i].Cells["数量"].Value) * (1 - Convert.ToDouble(grid生成新订单.Rows[i].Cells["折扣"].Value)); string str总价 = 总价.ToString("N"); ; grid生成新订单.Rows[i].Cells["单品总价"].Value = str总价; } } }
当用户点击新增按钮时,弹出新增按钮,注意这里必须以dialog的方式弹出,方便及时刷新数据。新增订单明细的窗体设计可以查看上图。
这个窗体需要实现的功能跟之前的新增雇员差不多,大家可以试着自己实现一下。
需要注意的地方有;
(1)要实现combobox的级联效应即选择完毕产品类别后可以自动加载产品名称
//当用户选择完毕产品类别后自动级联设置对应类别的产品名称 private void cbx产品类别_DropDownClosed(object sender, EventArgs e) { //当用户选中的选项是下拉菜单中的值 if (cbx产品类别.SelectedIndex != -1) { //为产品名称的combobox设置数据源,这是实现级联的关键代码 string strSQL = "SELECT * FROM 产品 WHERE 类别ID=" + cbx产品类别.SelectedValue; cbx产品名称.DataSource = SqlHelper.ExecuteDataset(SqlHelper.GetConnection(), CommandType.Text, strSQL).Tables[0]; cbx产品名称.ValueMember = "产品ID"; cbx产品名称.DisplayMember = "产品名称"; cbx产品名称.SelectedText = ""; } }
(2)当用户选择完毕产品名称后,自动显示产品单价。同样写在下拉菜单完毕的事件中。
//申明产品的搜索结果 public static int 产品库存量; //当用户选择完毕产品后自动设置对应产品的单价。 //注意:这里的产品为所有可用产品 private void cbx产品名称_DropDownClosed(object sender, EventArgs e) { if (cbx产品名称.SelectedValue != null) { string strSQL = "SELECT * FROM 产品 WHERE 中止='False' AND 库存量>0 AND 产品ID=" + cbx产品名称.SelectedValue; DataSet ds产品 = SqlHelper.ExecuteDataset(SqlHelper.GetConnection(), CommandType.Text, strSQL); if (ds产品.Tables[0].Rows.Count > 0) { tbx产品单价.Text = ds产品.Tables[0].Rows[0]["单价"].ToString(); //记录产品的库存量用于判断用户输入的订购量是否超出库存 产品库存量 = Convert.ToInt32(ds产品.Tables[0].Rows[0]["库存量"]); } else MessageBox.Show("查无此类产品,请重新选择", "输入错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
(3)订购数量与折扣的输入必须为数字的验证(自行完成)
(4)计算总价(自行完成)
(5)新增按钮的实现
//新增订单明细 private void btnAdd_Click(object sender, EventArgs e) { if (tbx产品单价.Text != "" && tbx订购数量.Text != "" && tbx折扣.Text != "" ) { //准备参数 string strSql = "INSERT INTO 订单明细 VALUES(@订单ID,@产品ID,@单价,@数量,@折扣)"; SqlParameter[] para = new SqlParameter[5]; para[0] = new SqlParameter("@订单ID",tbx订单ID.Text); para[1] = new SqlParameter("@产品ID", cbx产品名称.SelectedValue); para[2] = new SqlParameter("@单价", tbx产品单价.Text); para[3] = new SqlParameter("@数量", tbx订购数量.Text); para[4] = new SqlParameter("@折扣", tbx折扣.Text); int count = SqlHelper.ExecuteNonQuery(SqlHelper.GetConnection(), CommandType.Text, strSql, para); //判定是否有受影响的行数,如果有,说明插入成功了 if (count > 0) { MessageBox.Show("已成功订购 " + tbx订购数量.Text + " 个的" + cbx产品名称.Text + "(产品ID为" + cbx产品名称.SelectedValue + "),单品总价共 " + Calculat总价(tbx订购数量.Text, tbx产品单价.Text, tbx折扣.Text), "订购成功提示", MessageBoxButtons.OK, MessageBoxIcon.Information); this.Close(); } } else { MessageBox.Show("无法新增订单明细,请填写完整所有信息", "新增失败", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
//删除所有的订单明细 private void btn重置订单_Click(object sender, EventArgs e) { if (MessageBox.Show("确定清除本订单的所有产品记录吗?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes) { string strSQL = "DELETE FROM 订单明细 WHERE 订单ID='" + tbx订单ID.Text + "'"; int count = SqlHelper.ExecuteNonQuery(SqlHelper.GetConnection(), CommandType.Text, strSQL); if (count <= 0) { MessageBox.Show("删除记录操作异常,请检查", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error); } dataGridViewDatabing(); } }
为了避免工作失误,我们假定提交订单之前,先进行费用的确认。
确认运费按钮的点击事件为:
//加上运费,计算总体费用 private void btn确认费用_Click(object sender, EventArgs e) { if (tbx运货费用.Text == "" || !CommonFunc.IsNumberForInput(tbx运货费用.Text)) { MessageBox.Show("运货费用填写不规范", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error); tbx运货费用.Focus(); } else if (grid生成新订单.Rows.Count > 0) { double total = 0; for (int i = 0; i < grid生成新订单.Rows.Count; i++) { total += Convert.ToDouble(grid生成新订单.Rows[i].Cells["单品总价"].Value); } tbx产品总额.Text = total.ToString("C2"); total += Convert.ToDouble(tbx运货费用.Text); tbx总共金额.Text = total.ToString("C2"); } else { MessageBox.Show("本订单还未选择订购产品,没有费用可显示", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
而用户在确认提交订单时,需要注意这里必须需要操作两张表,一是订单表的记录添加,一是产品表的库存量减少。
private void btn确认提交_Click(object sender, EventArgs e) { if (tbx收货城市.Text == "") { MessageBox.Show("收货城市不能为空,请选择订购客户", "确认订单前提示", MessageBoxButtons.OK, MessageBoxIcon.Error); } else if (!rbtn急速快递.Checked && !rbtn统一包裹.Checked && !rbtn联邦货运.Checked) { MessageBox.Show("运货商不能为空,请选择运货商", "确认订单前提示", MessageBoxButtons.OK, MessageBoxIcon.Error); } else if (tbx总共金额.Text == "") { MessageBox.Show("尚未确认产品金额,请注意填写运费并确认总额", "确认订单前提示", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { //确认订单后需要操作两张表,一是订单表的记录添加,一是产品表的库存量减少 string str订单表 = "INSERT INTO 订单 VALUES(@订单ID,@客户ID,@雇员ID,@订购日期,@到货日期,@发货日期,@运货商,@运货费,@货主名称,@货主地址,@货主城市,@货主地区,@货主邮政编码,@货主国家)"; SqlParameter[] para = new SqlParameter[14]; para[0] = new SqlParameter("@订单ID", tbx订单ID.Text); para[1] = new SqlParameter("@客户ID", cbx客户名称.SelectedValue); para[2] = new SqlParameter("@雇员ID", CommonFunc.Get雇员ID()); para[3] = new SqlParameter("@订购日期", date订购日期.Value); para[4] = new SqlParameter("@到货日期", date到货日期.Value); para[5] = new SqlParameter("@发货日期", date发货日期.Value); para[6] = new SqlParameter("@运货商", Get运货商ID()); para[7] = new SqlParameter("@运货费", tbx运货费用.Text); para[8] = new SqlParameter("@货主名称", tbx收货单位.Text); para[9] = new SqlParameter("@货主地址", tbx收货地址.Text); para[10] = new SqlParameter("@货主城市", tbx收货城市.Text); para[11] = new SqlParameter("@货主地区", tbx收货地区.Text); para[12] = new SqlParameter("@货主邮政编码", tbx收货邮编.Text); para[13] = new SqlParameter("@货主国家", tbx收货国家.Text); int count = SqlHelper.ExecuteNonQuery(SqlHelper.GetConnection(), CommandType.Text, str订单表, para); //判定是否有受影响的行数,如果有,说明插入成功了 if (count > 0) { //进一步操作操作产品表的库存量 for (int i = 0; i < grid生成新订单.Rows.Count; i++) { int 产品ID = Convert.ToInt32(grid生成新订单.Rows[i].Cells["产品ID"].Value); int 订购量 = Convert.ToInt32(grid生成新订单.Rows[i].Cells["数量"].Value); int 原库存量 = Convert.ToInt32(SqlHelper.ExecuteScalar(SqlHelper.GetConnection(), CommandType.Text, "SELECT 库存量 FROM 产品 WHERE 产品ID=" + 产品ID)); int 新库存量 = 原库存量 - 订购量; int result = SqlHelper.ExecuteNonQuery(SqlHelper.GetConnection(), CommandType.Text, "UPDATE 产品 SET 库存量=" + 新库存量 + " WHERE 产品ID=" + 产品ID); if (result < 0) { MessageBox.Show("产品ID为 " + 产品ID.ToString() + " 的库存量修改失败,无法订购 ", "订购失败提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } } MessageBox.Show(cbx客户名称.Text + "已成功订购 " + grid生成新订单.Rows.Count + " 种产品,共计 " + tbx总共金额.Text + " 元(含运费)", "订购成功提示", MessageBoxButtons.OK, MessageBoxIcon.Information); this.Close(); } else { MessageBox.Show("订单ID为 " + tbx订单ID.Text+ " 的插入失败,无法订购 ", "订购失败提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } } }