private void btnSave_Click(object sender, EventArgs e)
        {
            if (!chkDocumentsOK.Checked)
            {
                if (txtNoteExecute.Text.Trim().Length == 0)
                {
                    RFMMessage.MessageBoxError("Не установлен признак \"Документы в порядке\".\n" +
                                               "Введите примечание к выполнению!");
                    txtNoteExecute.Select();
                    return;
                }
            }

            StringBuilder sbZero = new StringBuilder("");
            int           nZero = 0, nZeroSaid = 0;
            StringBuilder sbDiff = new StringBuilder("");
            int           nDiff = 0, nDiffSaid = 0;
            StringBuilder sbReturnZero = new StringBuilder("");
            int           nReturnZero = 0, nReturnZeroSaid = 0;
            StringBuilder sbReturnDiff = new StringBuilder("");
            int           nReturnDiff = 0, nReturnDiffSaid = 0;
            int           nReturnFirstID = -1;
            int           nLimit         = 10; // max число товаров при выводе проблем

            foreach (DataRow droOutGoods in oOutputDocument.TableOutputsDocumentsGoods.Rows)
            {
                if ((decimal)droOutGoods["QntBrought"] == 0)
                {
                    if ((decimal)droOutGoods["QntConfirmed"] > 0)
                    {
                        if (nZero < nLimit)
                        {
                            sbZero = sbZero.Append(droOutGoods["GoodAlias"].ToString() + "\n");
                            nZeroSaid++;
                        }
                        nZero++;

                        if (droOutGoods["ReturnReasonID"] == null || droOutGoods["ReturnReasonID"] == DBNull.Value)
                        {
                            if (nReturnZero < nLimit)
                            {
                                sbReturnZero = sbReturnZero.Append(droOutGoods["GoodAlias"].ToString() + "\n");
                                nReturnZeroSaid++;
                            }
                            nReturnZero++;

                            if (nReturnFirstID < 0)
                            {
                                nReturnFirstID = (int)droOutGoods["ID"];
                            }
                        }
                    }
                }
                else
                {
                    if ((decimal)droOutGoods["QntBrought"] != (decimal)droOutGoods["QntConfirmed"])
                    {
                        if (nDiff < nLimit)
                        {
                            sbDiff = sbDiff.Append(droOutGoods["GoodAlias"].ToString() + "\n");
                            nDiffSaid++;
                        }
                        nDiff++;

                        if (droOutGoods["ReturnReasonID"] == null || droOutGoods["ReturnReasonID"] == DBNull.Value)
                        {
                            if (nReturnDiff < nLimit)
                            {
                                sbReturnDiff = sbReturnDiff.Append(droOutGoods["GoodAlias"].ToString() + "\n");
                                nReturnDiffSaid++;
                            }
                            nReturnDiff++;

                            if (nReturnFirstID < 0)
                            {
                                nReturnFirstID = (int)droOutGoods["ID"];
                            }
                        }
                    }
                }
            }

            if (nZero > 0)
            {
                if (nZero == oOutputDocument.TableOutputsDocumentsGoods.Rows.Count)
                {
                    if (RFMMessage.MessageBoxYesNo("Ни один товар не доставлен получателю.\n\n" +
                                                   "Все-таки подтвердить доставку заказа?") == DialogResult.No)
                    {
                        return;
                    }
                }
                else
                {
                    if (nZero - nZeroSaid > 0)
                    {
                        sbZero = sbZero.Append("и еще " + RFMUtilities.Declen(nZero - nZeroSaid, "товар", "товара", "товаров") + "\n");
                    }
                    if (RFMMessage.MessageBoxYesNo("Следующие товары:\n" + sbZero + "не доставлены получателю.\n\n" +
                                                   "Все-таки подтвердить доставку заказа?") == DialogResult.No)
                    {
                        return;
                    }
                }
            }

            if (nDiff > 0)
            {
                if (nDiff - nDiffSaid > 0)
                {
                    sbDiff = sbDiff.Append("и еще " + RFMUtilities.Declen(nDiff - nDiffSaid, "товара", "товаров", "товаров") + "\n");
                }
                if (RFMMessage.MessageBoxYesNo("Для следующих товаров:\n" + sbDiff + "доставленное количество не равно отгруженному.\n\n" +
                                               "Все-таки подтвердить доставку заказа?") == DialogResult.No)
                {
                    return;
                }
            }

            // причины возврата
            if (nReturnZero > 0)
            {
                if (nReturnZero == oOutputDocument.TableOutputsDocumentsGoods.Rows.Count)
                {
                    /*
                     * if (RFMMessage.MessageBoxYesNo("Ни один товар не доставлен получателю,\n" +
                     *      "ни для одного товара не указаны причины возврата.\n\n" +
                     *      "Перенос заказа не был выполнен!\n\n" +
                     *      "Все-таки подтвердить доставку заказа?") == DialogResult.No)
                     *      return;
                     */
                    RFMMessage.MessageBoxError("Ни один товар не доставлен получателю,\n" +
                                               "ни для одного товара не указаны причины возврата.\n\n" +
                                               "Перенос заказа не был выполнен!\n\n" +
                                               "Подтверждение доставки заказа не выполняется!");
                    return;
                }
                else
                {
                    if (nReturnZero - nReturnZeroSaid > 0)
                    {
                        sbReturnZero = sbReturnZero.Append("и еще " + RFMUtilities.Declen(nReturnZero - nReturnZeroSaid, "товар", "товара", "товаров") + "\n");
                    }

                    /*
                     * if (RFMMessage.MessageBoxYesNo("Следующие товары:\n" + sbReturnZero + "не доставлены получателю и\n" +
                     *      "для них не указана причина возврата.\n\n" +
                     *      "Все-таки подтвердить доставку заказа?") == DialogResult.No)
                     *      return;
                     */
                    RFMMessage.MessageBoxError("Следующие товары:\n" + sbReturnZero + "не доставлены получателю и\n" +
                                               "для них не указана причина возврата.\n\n" +
                                               "Подтверждение доставки заказа не выполняется!");

                    if (nReturnFirstID >= 0)
                    {
                        int nGridPosition = ((RFMBindingSource)dgvOutputsDocumentsGoods.GridSource).Find("ID", nReturnFirstID);
                        if (nGridPosition >= 0)
                        {
                            dgvOutputsDocumentsGoods.GridSource.Position = nGridPosition;
                        }
                    }
                    return;
                }
            }

            if (nReturnDiff > 0)
            {
                if (nReturnDiff - nReturnDiffSaid > 0)
                {
                    sbReturnDiff = sbReturnDiff.Append("и еще " + RFMUtilities.Declen(nReturnDiff - nReturnDiffSaid, "товара", "товаров", "товаров") + "\n");
                }

                /*
                 * if (RFMMessage.MessageBoxYesNo("Для следующих товаров:\n" + sbReturnDiff + "доставленное количество не равно отгруженному и\n" +
                 *      "и не указана причина возврата.\n\n" +
                 *      "Все-таки подтвердить доставку заказа?") == DialogResult.No)
                 *      return;
                 */
                RFMMessage.MessageBoxError("Для следующих товаров:\n" + sbReturnDiff + "доставленное количество не равно отгруженному и\n" +
                                           "и не указана причина несоответствия отгруженного и доставленного количества.\n\n" +
                                           "Подтверждение доставки заказа не выполняется!");

                if (nReturnFirstID >= 0)
                {
                    int nGridPosition = ((RFMBindingSource)dgvOutputsDocumentsGoods.GridSource).Find("ID", nReturnFirstID);
                    if (nGridPosition >= 0)
                    {
                        dgvOutputsDocumentsGoods.GridSource.Position = nGridPosition;
                    }
                }
                return;
            }

            /*
             * // по кол-ву денег
             * if (numGetMoneyWished.Value != numGetMoneyConfirmed.Value)
             * {
             *      if (RFMMessage.MessageBoxYesNo("Не совпадает сумма:\n" +
             *              "ожидаемая (" + numGetMoneyWished.Value.ToString("### ### ##0.00").Trim() + ") и полученная (" + numGetMoneyConfirmed.Value.ToString("### ### ##0.00").Trim() + ").\n\n" +
             *              "Все-таки подтвердить доставку заказа?") == DialogResult.No)
             *              return;
             * }
             * if (numGetMoneyWished.Value != 0 && numGetMoneyConfirmed.Value == 0 &&
             *      !chkIsWarrantReturned.Checked)
             * {
             *      if (RFMMessage.MessageBoxYesNo("Не указана полученная сумма,\n" +
             *              "не указано также, что доверенность возвращена.\n\n" +
             *              "Все-таки подтвердить?") == DialogResult.No)
             *              return;
             * }
             * if (numGetMoneyConfirmed.Value != 0 &&
             *      chkIsWarrantReturned.Checked)
             * {
             *      if (RFMMessage.MessageBoxYesNo("Указана полученная сумма,\n" +
             *              "указано также, что доверенность возвращена.\n\n" +
             *              "Все-таки подтвердить?") == DialogResult.No)
             *              return;
             * }
             */

            // по паллетам
            if (numGetPalletsQntWished.Value != numGetPalletsQntConfirmed.Value)
            {
                if (RFMMessage.MessageBoxYesNo("Не совпадает количество паллет:\n" +
                                               "ожидаемое (" + numGetPalletsQntWished.Value.ToString("#####0").Trim() + ") и полученное (" + numGetPalletsQntConfirmed.Value.ToString("#####0").Trim() + ").\n\n" +
                                               "Все-таки подтвердить доставку заказа?") == DialogResult.No)
                {
                    return;
                }
            }

            // добрались. уже сохраняем

            if (true)             // (RFMMessage.MessageBoxYesNo("Подтвердить доставку заказа получателю?") == DialogResult.Yes)
            {
                oOutputDocument.NoteExecute = txtNoteExecute.Text.Trim();
                oOutputDocument.DocumentsOK = chkDocumentsOK.Checked;

                /*
                 * oOutputDocument.GetMoneyConfirmed = numGetMoneyConfirmed.Value;
                 * oOutputDocument.IsWarrantReturned = chkIsWarrantReturned.Checked;
                 */
                oOutputDocument.GetPalletsQntConfirmed = (int)numGetPalletsQntConfirmed.Value;

                // добрались. сохраняем.
                Refresh();
                WaitOn(this);
                oOutputDocument.ClearError();
                bool bResult = oOutputDocument.Bring(((RFMFormBase)Application.OpenForms[0]).UserInfo.UserID);
                WaitOff(this);
                if (bResult && oOutputDocument.ErrorNumber == 0)
                {
                    //RFMMessage.MessageBoxInfo("Зарегистрирована доставка заказа получателю.");
                    DialogResult = DialogResult.Yes;
                    Dispose();
                }
            }
        }