// 01/05/2007 Paul.  We need to update the totals before saving.
        public void UpdateTotals()
        {
            Double dSUBTOTAL = 0.0;
            Double dDISCOUNT = new DynamicControl(this, "DISCOUNT").FloatValue;
            Double dSHIPPING = new DynamicControl(this, "SHIPPING").FloatValue;
            Double dTAX      = 0.0;
            Double dTOTAL    = 0.0;
            double dTAX_RATE = 0.0;

            DataTable dtTAX_RATE = SplendidCache.TaxRates();

            if (!Sql.IsEmptyGuid(TAXRATE_ID.SelectedValue))
            {
                DataRow[] row = dtTAX_RATE.Select("ID = '" + TAXRATE_ID.SelectedValue + "'");
                if (row.Length == 1)
                {
                    dTAX_RATE = Sql.ToDouble(row[0]["VALUE"]) / 100;
                }
            }
            foreach (DataRow row in dtLineItems.Rows)
            {
                if (row.RowState != DataRowState.Deleted)
                {
                    // 08/11/2007 Paul.  Allow an item to be manually added.  Require either a product ID or a name.
                    if (!Sql.IsEmptyString(row["NAME"]) || !Sql.IsEmptyGuid(row["PRODUCT_TEMPLATE_ID"]))
                    {
                        string sLINE_ITEM_TYPE = Sql.ToString(row["LINE_ITEM_TYPE"]);
                        string sTAX_CLASS      = Sql.ToString(row["TAX_CLASS"]);
                        int    nQUANTITY       = Sql.ToInteger(row["QUANTITY"]);
                        Double dUNIT_PRICE     = Sql.ToDouble(row["UNIT_PRICE"]);
                        if (sLINE_ITEM_TYPE != "Comment")
                        {
                            dSUBTOTAL += dUNIT_PRICE * nQUANTITY;
                            if (sTAX_CLASS == "Taxable")
                            {
                                dTAX += dUNIT_PRICE * nQUANTITY * dTAX_RATE;
                            }
                        }
                    }
                }
            }
            dTOTAL        = dSUBTOTAL - dDISCOUNT + dTAX + dSHIPPING;
            SUBTOTAL.Text = Convert.ToDecimal(dSUBTOTAL).ToString("c");
            DISCOUNT.Text = Convert.ToDecimal(dDISCOUNT).ToString("0.00");
            SHIPPING.Text = Convert.ToDecimal(dSHIPPING).ToString("0.00");
            TAX.Text      = Convert.ToDecimal(dTAX).ToString("c");
            TOTAL.Text    = Convert.ToDecimal(dTOTAL).ToString("c");
            // 03/31/2007 Paul.  We are using UNIT_PRICE, so the value will need to be converted to USD before stored in hidden fields.
            DISCOUNT_USDOLLAR.Value = C10n.FromCurrency(Convert.ToDecimal(dDISCOUNT)).ToString("0.000");
            SHIPPING_USDOLLAR.Value = C10n.FromCurrency(Convert.ToDecimal(dSHIPPING)).ToString("0.000");
        }
        private void UpdateTotals()
        {
            Double dALLOCATED = 0.0;

            foreach (DataRow row in dtLineItems.Rows)
            {
                if (row.RowState != DataRowState.Deleted)
                {
                    Double dAMOUNT = Sql.ToDouble(row["AMOUNT"]);
                    dALLOCATED += dAMOUNT;
                }
            }
            ALLOCATED.Text           = Convert.ToDecimal(dALLOCATED).ToString("c");
            ALLOCATED_USDOLLAR.Value = C10n.FromCurrency(Convert.ToDecimal(dALLOCATED)).ToString("0.000");
        }
        protected void grdMain_RowUpdating(object sender, GridViewUpdateEventArgs e)
        {
            if (dtLineItems != null)
            {
                GridViewRow gr = grdMain.Rows[e.RowIndex];
                TextBox     txtINVOICE_NAME    = gr.FindControl("INVOICE_NAME") as TextBox;
                HiddenField txtINVOICE_ID      = gr.FindControl("INVOICE_ID") as HiddenField;
                TextBox     txtAMOUNT          = gr.FindControl("AMOUNT") as TextBox;
                HiddenField txtAMOUNT_USDOLLAR = gr.FindControl("AMOUNT_USDOLLAR") as HiddenField;

                DataRow row = dtLineItems.Rows[e.RowIndex];
                // 03/31/2007 Paul.  The US Dollar values are computed from the price and are only used when changing currencies.
                if (txtINVOICE_NAME != null)
                {
                    row["INVOICE_NAME"] = txtINVOICE_NAME.Text;
                }
                if (txtINVOICE_ID != null)
                {
                    row["INVOICE_ID"] = Sql.ToGuid(txtINVOICE_ID.Value);
                }
                if (txtAMOUNT != null)
                {
                    row["AMOUNT"] = Sql.ToDecimal(txtAMOUNT.Text);
                }

                row["AMOUNT_USDOLLAR"] = C10n.FromCurrency(Sql.ToDecimal(txtAMOUNT.Text));

                DataRow[] aCurrentRows = dtLineItems.Select(String.Empty, String.Empty, DataViewRowState.CurrentRows);
                // 03/30/2007 Paul.  Always allow editing of the last empty row. Add blank row if necessary.
                if (aCurrentRows.Length == 0 || !Sql.IsEmptyString(aCurrentRows[aCurrentRows.Length - 1]["INVOICE_NAME"]))
                {
                    DataRow rowNew = dtLineItems.NewRow();
                    dtLineItems.Rows.Add(rowNew);
                    aCurrentRows = dtLineItems.Select(String.Empty, String.Empty, DataViewRowState.CurrentRows);
                }

                ViewState["LineItems"] = dtLineItems;
                grdMain.DataSource     = dtLineItems;
                // 03/30/2007 Paul.  Make sure to use the last row of the current set, not the total rows of the table.  Some rows may be deleted.
                grdMain.EditIndex = aCurrentRows.Length - 1;
                grdMain.DataBind();
                UpdateTotals();
            }
        }
        protected void grdMain_RowUpdating(object sender, GridViewUpdateEventArgs e)
        {
            if (dtLineItems != null)
            {
                GridViewRow  gr = grdMain.Rows[e.RowIndex];
                HiddenField  txtLINE_ITEM_TYPE      = gr.FindControl("LINE_ITEM_TYPE") as HiddenField;
                TextBox      txtNAME                = gr.FindControl("NAME") as TextBox;
                TextBox      txtMFT_PART_NUM        = gr.FindControl("MFT_PART_NUM") as TextBox;
                HiddenField  txtVENDOR_PART_NUM     = gr.FindControl("VENDOR_PART_NUM") as HiddenField;
                HiddenField  txtPRODUCT_TEMPLATE_ID = gr.FindControl("PRODUCT_TEMPLATE_ID") as HiddenField;
                DropDownList lstTAX_CLASS           = gr.FindControl("TAX_CLASS") as DropDownList;
                TextBox      txtQUANTITY            = gr.FindControl("QUANTITY") as TextBox;
                TextBox      txtCOST_PRICE          = gr.FindControl("COST_PRICE") as TextBox;
                HiddenField  txtCOST_USDOLLAR       = gr.FindControl("COST_USDOLLAR") as HiddenField;
                TextBox      txtLIST_PRICE          = gr.FindControl("LIST_PRICE") as TextBox;
                HiddenField  txtLIST_USDOLLAR       = gr.FindControl("LIST_USDOLLAR") as HiddenField;
                TextBox      txtUNIT_PRICE          = gr.FindControl("UNIT_PRICE") as TextBox;
                HiddenField  txtUNIT_USDOLLAR       = gr.FindControl("UNIT_USDOLLAR") as HiddenField;
                TextBox      txtEXTENDED_PRICE      = gr.FindControl("EXTENDED_PRICE") as TextBox;
                HiddenField  txtEXTENDED_USDOLLAR   = gr.FindControl("EXTENDED_USDOLLAR") as HiddenField;
                TextBox      txtDESCRIPTION         = gr.FindControl("DESCRIPTION") as TextBox;

                //DataRow row = dtLineItems.Rows[e.RowIndex];
                // 12/07/2007 garf.  If there are deleted rows in the set, then the index will be wrong.  Make sure to use the current rowset.
                DataRow[] aCurrentRows = dtLineItems.Select(String.Empty, String.Empty, DataViewRowState.CurrentRows);
                DataRow   row          = aCurrentRows[e.RowIndex];
                // 03/30/2007 Paul.  The text controls are empty.  Use the Request object to read the data.
                if (txtLINE_ITEM_TYPE != null)
                {
                    row["LINE_ITEM_TYPE"] = txtLINE_ITEM_TYPE.Value;
                }
                if (txtDESCRIPTION != null)
                {
                    row["DESCRIPTION"] = txtDESCRIPTION.Text;
                }
                if (Sql.ToString(row["LINE_ITEM_TYPE"]) == "Comment")
                {
                    row["NAME"]                = DBNull.Value;
                    row["MFT_PART_NUM"]        = DBNull.Value;
                    row["VENDOR_PART_NUM"]     = DBNull.Value;
                    row["PRODUCT_TEMPLATE_ID"] = DBNull.Value;
                    row["TAX_CLASS"]           = DBNull.Value;
                    row["QUANTITY"]            = DBNull.Value;
                    row["COST_PRICE"]          = DBNull.Value;
                    row["COST_USDOLLAR"]       = DBNull.Value;
                    row["LIST_PRICE"]          = DBNull.Value;
                    row["LIST_USDOLLAR"]       = DBNull.Value;
                    row["UNIT_PRICE"]          = DBNull.Value;
                    row["UNIT_USDOLLAR"]       = DBNull.Value;
                    row["EXTENDED_PRICE"]      = DBNull.Value;
                    row["EXTENDED_USDOLLAR"]   = DBNull.Value;
                }
                else
                {
                    // 03/31/2007 Paul.  The US Dollar values are computed from the price and are only used when changing currencies.
                    if (txtNAME != null)
                    {
                        row["NAME"] = txtNAME.Text;
                    }
                    if (txtMFT_PART_NUM != null)
                    {
                        row["MFT_PART_NUM"] = txtMFT_PART_NUM.Text;
                    }
                    if (txtVENDOR_PART_NUM != null)
                    {
                        row["VENDOR_PART_NUM"] = txtVENDOR_PART_NUM.Value;
                    }
                    if (txtPRODUCT_TEMPLATE_ID != null)
                    {
                        row["PRODUCT_TEMPLATE_ID"] = Sql.ToGuid(txtPRODUCT_TEMPLATE_ID.Value);
                    }
                    if (lstTAX_CLASS != null)
                    {
                        row["TAX_CLASS"] = lstTAX_CLASS.SelectedValue;
                    }
                    if (txtQUANTITY != null)
                    {
                        row["QUANTITY"] = Sql.ToInteger(txtQUANTITY.Text);
                    }
                    if (txtCOST_PRICE != null)
                    {
                        row["COST_PRICE"] = Sql.ToDecimal(txtCOST_PRICE.Text);
                    }
                    if (txtLIST_PRICE != null)
                    {
                        row["LIST_PRICE"] = Sql.ToDecimal(txtLIST_PRICE.Text);
                    }
                    if (txtUNIT_PRICE != null)
                    {
                        row["UNIT_PRICE"] = Sql.ToDecimal(txtUNIT_PRICE.Text);
                    }

                    row["COST_USDOLLAR"]     = C10n.FromCurrency(Sql.ToDecimal(txtCOST_PRICE.Text));
                    row["LIST_USDOLLAR"]     = C10n.FromCurrency(Sql.ToDecimal(txtLIST_PRICE.Text));
                    row["UNIT_USDOLLAR"]     = C10n.FromCurrency(Sql.ToDecimal(txtUNIT_PRICE.Text));
                    row["EXTENDED_PRICE"]    = Sql.ToInteger(row["QUANTITY"]) * Sql.ToDecimal(row["UNIT_PRICE"]);
                    row["EXTENDED_USDOLLAR"] = C10n.FromCurrency(Sql.ToDecimal(row["EXTENDED_PRICE"]));
                }

                // 12/07/2007 Paul.  aCurrentRows is defined above.
                //DataRow[] aCurrentRows = dtLineItems.Select(String.Empty, String.Empty, DataViewRowState.CurrentRows);
                // 03/30/2007 Paul.  Always allow editing of the last empty row. Add blank row if necessary.
                // 08/11/2007 Paul.  Allow an item to be manually added.  Require either a product ID or a name.
                if (aCurrentRows.Length == 0 || !Sql.IsEmptyString(aCurrentRows[aCurrentRows.Length - 1]["NAME"]) || !Sql.IsEmptyGuid(aCurrentRows[aCurrentRows.Length - 1]["PRODUCT_TEMPLATE_ID"]))
                {
                    DataRow rowNew = dtLineItems.NewRow();
                    dtLineItems.Rows.Add(rowNew);
                    aCurrentRows = dtLineItems.Select(String.Empty, String.Empty, DataViewRowState.CurrentRows);
                }

                ViewState["LineItems"] = dtLineItems;
                grdMain.DataSource     = dtLineItems;
                // 03/30/2007 Paul.  Make sure to use the last row of the current set, not the total rows of the table.  Some rows may be deleted.
                grdMain.EditIndex = aCurrentRows.Length - 1;
                grdMain.DataBind();
                UpdateTotals();
            }
        }