private void btnSave_Click(object sender, EventArgs e)
        {
            bool _isSaved = false;

            if (treeData.AllNodesCount == 0)
            {
                return;
            }
            treeData.ExpandAll();
            treeData.FocusedNode = null;

            using (WaitDialogForm fWait = new WaitDialogForm("Vui lòng chờ trong giây lát...", "Đang xử lý..."))
            {
                for (int i = 0; i < treeData.AllNodesCount; i++)
                {
                    int id = TextUtils.ToInt(treeData.GetNodeByVisibleIndex(i).GetValue(colDetailID));
                    C_QuotationDetailModel item = (C_QuotationDetailModel)C_QuotationDetailBO.Instance.FindByPK(id);

                    item.ModuleCode = TextUtils.ToString(treeData.GetNodeByVisibleIndex(i).GetValue(colModuleCode));
                    item.ModuleName = TextUtils.ToString(treeData.GetNodeByVisibleIndex(i).GetValue(colModuleName));
                    item.PriceVTLD  = TextUtils.ToDecimal(treeData.GetNodeByVisibleIndex(i).GetValue(colPriceVTLD));
                    item.PriceVTPS  = TextUtils.ToDecimal(treeData.GetNodeByVisibleIndex(i).GetValue(colPriceVTPS));
                    item.PriceVTSX  = TextUtils.ToDecimal(treeData.GetNodeByVisibleIndex(i).GetValue(colPriceVTSX));
                    item.PriceVTTN  = TextUtils.ToDecimal(treeData.GetNodeByVisibleIndex(i).GetValue(colPriceVTTN));

                    item.PriceVT = item.PriceVTSX + item.PriceVTLD + item.PriceVTPS + item.PriceVTTN;

                    item.PriceHD = TextUtils.ToDecimal(treeData.GetNodeByVisibleIndex(i).GetValue(colPriceHD));

                    item.C_ProductGroupID = TextUtils.ToInt(treeData.GetNodeByVisibleIndex(i).GetValue(colProductGroupID));
                    item.VAT  = TextUtils.ToDecimal(treeData.GetNodeByVisibleIndex(i).GetValue(colVAT));
                    item.QtyT = TextUtils.ToDecimal(treeData.GetNodeByVisibleIndex(i).GetValue(colQtyT));

                    int parentID = TextUtils.ToInt(treeData.GetNodeByVisibleIndex(i).GetValue(colParentID));
                    if (parentID == 0)
                    {
                        item.Qty = item.QtyT;
                    }
                    else
                    {
                        C_QuotationDetailModel parent = (C_QuotationDetailModel)C_QuotationDetailBO.Instance.FindByPK(parentID);
                        item.Qty = item.QtyT * parent.Qty;
                    }

                    C_QuotationDetailBO.Instance.Update(item);
                }

                DataTable dtCostVT = LibQLSX.Select("select sum(Qty*PriceVT) from C_QuotationDetail where (ParentID > 0 or (ParentID = 0 and C_ProductGroupID > 0)) and [C_QuotationID] = " + Quotation.ID);
                decimal   costVT   = dtCostVT.Rows.Count > 0 ? TextUtils.ToDecimal(dtCostVT.Rows[0][0]) : 0;

                for (int i = 0; i < treeData.AllNodesCount; i++)
                {
                    int id = TextUtils.ToInt(treeData.GetNodeByVisibleIndex(i).GetValue(colDetailID));
                    C_QuotationDetailModel item = (C_QuotationDetailModel)C_QuotationDetailBO.Instance.FindByPK(id);

                    if (item.ParentID == 0 && item.C_ProductGroupID == 0)
                    {
                        continue;
                    }

                    DataTable dtProductGroup = LibQLSX.Select("select ProfitPercent, CustomerPercent from C_ProductGroup where ID = " + item.C_ProductGroupID);
                    decimal   profitPercent  = dtProductGroup.Rows.Count > 0 ? TextUtils.ToDecimal(dtProductGroup.Rows[0]["ProfitPercent"]) / 100 : 0;

                    decimal customerPercent = 0;
                    if (Quotation.IsVAT < 2)
                    {
                        customerPercent = dtProductGroup.Rows.Count > 0 ? TextUtils.ToDecimal(dtProductGroup.Rows[0]["CustomerPercent"]) / 100 : 0;
                    }

                    decimal percentPB        = LibQLSX.GetPercentCostPB(item.C_ProductGroupID, Quotation.DeliveryTime) / 100;
                    decimal priceTPA         = 0;
                    decimal nhanCongTrucTiep = item.TotalNC;
                    decimal costTrienKhai    = Quotation.TotalCustomer * item.PriceVT / costVT;
                    decimal tienMat          = Quotation.CustomerCash * item.PriceVT / costVT;
                    decimal percentKH        = Quotation.CustomerPercent / 100;

                    //Gsx = CP + CP * %LN
                    //Gsx = VT + NC + TrienKhai + %PB * Gsx + (VT + NC + TrienKhai + %PB * Gsx) * %LN
                    //Gsx = (VT+NC+TrienKhai)(1+%LN) + Gsx(%PB+%PB*%LN)
                    //Gsx - Gsx(%PB+%PB*%LN) = (VT+NC+TrienKhai)(1+%LN)
                    //Gsx = (VT+NC+TrienKhai)(1+%LN)/(1-%PB-%PB*%LN)
                    //decimal priceSX = (item.PriceVT + nhanCongTrucTiep + costTrienKhai) * (1 + profitPercent) / (1 - percentPB - percentPB * profitPercent);
                    //priceTPA = (priceSX + (1 + customerPercent) * tienMat) / (1 - (1 + customerPercent) * percentKH - (1 - 1 / (1 + item.VAT / 100)));

                    //Gb = VTU + CPDA.NC  + CPDA.TKHAI + (1-1/(1+%VAT))*Gb + (tienMat+%KH*Gb) + %PB*(Gb-(tienMat+percentKH*Gb)) + 0.15*(tienMat+%KH*Gb) + %LN*Gb
                    //Gb = (VTU + CPDA.NC  + CPDA.TKHAI +(1.15- %PB)* tienMat)/ (1/(1+%VAT) - %PB + %PB*%KH -1.15*%KH - %LN)

                    decimal priceTPA1 = (item.PriceVT + nhanCongTrucTiep + costTrienKhai + tienMat + customerPercent * tienMat - percentPB * tienMat - tienMat * profitPercent) //percentKH * item.PriceHD
                                        / (1 - (1 - 1 / (1 + item.VAT / 100)) - percentKH - percentPB - profitPercent + percentKH * percentPB + percentKH * profitPercent);

                    if (item.PriceHD == 0)
                    {
                        decimal priceTPA2 = priceTPA1 + (customerPercent * percentKH * priceTPA1)
                                            / (1 - (1 - 1 / (1 + item.VAT / 100)) - percentKH - percentPB - profitPercent + percentKH * percentPB + percentKH * profitPercent);
                        item.PriceHD = priceTPA2;
                    }

                    priceTPA = priceTPA1 + (customerPercent * percentKH * item.PriceHD)
                               / (1 - (1 - 1 / (1 + item.VAT / 100)) - percentKH - percentPB - profitPercent + percentKH * percentPB + percentKH * profitPercent);

                    item.PriceReal = item.PriceHD - (percentKH * item.PriceHD + tienMat);
                    item.TotalCP   = (item.PriceVT + nhanCongTrucTiep + costTrienKhai) + percentPB * item.PriceReal;
                    item.PriceSX   = item.TotalCP;
                    //decimal pricePBTPA = percentPB * (priceTPA - tienMat - percentKH * priceTPA);
                    //priceTPA += percentPB * item.PriceReal - pricePBTPA;

                    item.PriceTPA    = priceTPA;
                    item.TotalProfit = profitPercent * item.PriceReal;
                    C_QuotationDetailBO.Instance.Update(item);

                    calculateCost(item, costVT);
                }

                ArrayList listParent = C_QuotationDetailBO.Instance.FindByExpression(new Expression("ParentID", 0)
                                                                                     .And(new Expression("C_ProductGroupID", 0))
                                                                                     .And(new Expression("C_QuotationID", Quotation.ID)));

                if (listParent != null)
                {
                    foreach (var item in listParent)
                    {
                        C_QuotationDetailModel itemP = (C_QuotationDetailModel)item;
                        DataTable dtChild            = LibQLSX.Select("select Sum(QtyT*PriceVTLD),Sum(QtyT*PriceVTPS),Sum(QtyT*PriceVTSX),Sum(QtyT*PriceVTTN),Sum(QtyT*PriceTPA),Sum(QtyT*PriceHD) from C_QuotationDetail where ParentID = " + itemP.ID);

                        itemP.PriceVTLD = dtChild.Rows.Count > 0 ? TextUtils.ToDecimal(dtChild.Rows[0][0]) : itemP.PriceVTLD;
                        itemP.PriceVTPS = dtChild.Rows.Count > 0 ? TextUtils.ToDecimal(dtChild.Rows[0][1]) : itemP.PriceVTPS;
                        itemP.PriceVTSX = dtChild.Rows.Count > 0 ? TextUtils.ToDecimal(dtChild.Rows[0][2]) : itemP.PriceVTSX;
                        itemP.PriceVTTN = dtChild.Rows.Count > 0 ? TextUtils.ToDecimal(dtChild.Rows[0][3]) : itemP.PriceVTTN;
                        itemP.PriceTPA  = dtChild.Rows.Count > 0 ? TextUtils.ToDecimal(dtChild.Rows[0][4]) : itemP.PriceTPA;
                        itemP.PriceHD   = dtChild.Rows.Count > 0 ? TextUtils.ToDecimal(dtChild.Rows[0][5]) : itemP.PriceHD;
                        itemP.PriceVT   = itemP.PriceVTSX + itemP.PriceVTLD + itemP.PriceVTPS + itemP.PriceVTTN;

                        C_QuotationDetailBO.Instance.Update(itemP);
                    }
                }

                loadQuotationItem();
                _isSaved = true;
            }

            MessageBox.Show("Lưu trữ thành công.", TextUtils.Caption, MessageBoxButtons.OK, MessageBoxIcon.Information);

            if (_isSaved)
            {
                if (this.LoadDataChange != null)
                {
                    this.LoadDataChange(null, null);
                }
            }
        }