Base file: Документ_ЧекККМ_МодульОбъекта.onec

Compared file: Документ_ЧекККМ_МодульОбъекта.m000.onec

Generated by CSDiff on 27.03.2013 13:34  

 
////////////////////////////////////////////////////////////////////////////////
// ПЕРЕМЕННЫЕ МОДУЛЯ

// Переменная, указывающая что проведение чека производится из
// режима регистрации продаж
Перем РежимРМК Экспорт;

// Переменная определяет режим в котором происходит запись документа
Перем мЗакрытиеСмены;

Перем КонтролироватьОстаткиТоваровПриЗакрытииЧека Экспорт;

Перем мСоответствиеТиповСкладов;

//m000 Запись документ для возврата
&НаСервере
Процедура ЗаписатьДанныеПоДокументуВозврат(АМассивТоваров, АСсылкаНаОснование, АСсылкаНаДвижение)
    
    //АМассивТоваров       список товаров к возврату (Код транзакции отсутствует)
    //АСсылкаНаОснование   документ - основание, т.е. ЧекККМ продажи
    
    ВыборкаДокументовДвиженияПокупка = Документы.m000Скидка.НайтиПоРеквизиту("Документ", АСсылкаНаОснование);
    
    Если ВыборкаДокументовДвиженияПокупка.Ссылка <> Документы.m000Скидка.ПустаяСсылка() Тогда
        ДокументДвиженияПокупка = ВыборкаДокументовДвиженияПокупка.ПолучитьОбъект();
    КонецЕсли;
    
    ВыборкаДокументовДвиженияВозврат = Документы.m000Скидка.НайтиПоРеквизиту("Документ", ЭтотОбъект.Ссылка);
    
    Если ВыборкаДокументовДвиженияВозврат.Ссылка <> Документы.m000Скидка.ПустаяСсылка() Тогда
        ДокументДвиженияВозврат = ВыборкаДокументовДвиженияВозврат.ПолучитьОбъект();
    Иначе
        ДокументДвиженияВозврат = Документы.m000Скидка.СоздатьДокумент();
    КонецЕсли;
    
    
    ДокументДвиженияВозврат = Документы.m000Скидка.СоздатьДокумент();
    
    ДокументДвиженияВозврат.Документ        = ЭтотОбъект.Ссылка;
    ДокументДвиженияВозврат.Дата            = ЭтотОбъект.Дата;
    ДокументДвиженияВозврат.Акция           = ДокументДвиженияПокупка.Акция;
    ДокументДвиженияВозврат.Пользователь    = ДокументДвиженияПокупка.Пользователь;
    ДокументДвиженияВозврат.ДисконтнаяКарта = ДокументДвиженияПокупка.ДисконтнаяКарта;
    
    ДокументДвиженияВозврат.Сумма           = ДокументДвиженияПокупка.Сумма;
    ДокументДвиженияВозврат.СуммаСкидки     = ДокументДвиженияПокупка.СуммаСкидки;
    ДокументДвиженияВозврат.Начислено       = Ложь;
    
    
    ДокументДвиженияВозврат.ТаблицаДвижений.Очистить();
    Для Каждого СтрокаТоваров Из АМассивТоваров Цикл
        Для Каждого СтрокаТоваровПокупка Из ДокументДвиженияПокупка.ТаблицаДвижений Цикл        
            
            Если СтрокаТоваров.Номенклатура.Ссылка =  СтрокаТоваровПокупка.Номенклатура.Ссылка Тогда
                НоваяСтрока              = ДокументДвиженияВозврат.ТаблицаДвижений.Добавить();          
                НоваяСтрока.Акция        = СтрокаТоваровПокупка.Акция;
                НоваяСтрока.Номенклатура = СтрокаТоваровПокупка.Номенклатура;
                НоваяСтрока.Сумма        = СтрокаТоваров.Сумма;     
                НоваяСтрока.СуммаСкидки  = 0; //Скидка уже в сумме
                НоваяСтрока.КодТранзакции= СтрокаТоваровПокупка.КодТранзакции;
            КонецЕсли;
            
        КонецЦикла;             
    КонецЦикла; 
    
    ДокументДвиженияВозврат.Записать(РежимЗаписиДокумента.Запись);

    АСсылкаНаДвижение =  ДокументДвиженияВозврат.Ссылка;
    
КонецПроцедуры  
//m000/


////////////////////////////////////////////////////////////////////////////////
// ЭКСПОРТНЫЕ ПРОЦЕДУРЫ И ФУНКЦИИ ДОКУМЕНТА

#Если Клиент Тогда


// Процедура осуществляет печать документа. Можно направить печать на 

// экран или принтер, а также распечатать необходмое количество копий.

//

//  Название макета печати передается в качестве параметра,

// по переданному названию находим имя макета в соответствии.

//

// Параметры:

//  НазваниеМакета - строка, название макета.

//

Процедура Печать(ИмяМакета, КоличествоЭкземпляров = 1, НаПринтер = Ложь) Экспорт

    
    ПечататьВозвратныеЗаявления = Ложь;
    

    Если ЭтоНовый() Тогда

        Предупреждение("Документ можно распечатать только после его записи");

        Возврат;

    ИначеЕсли Не УправлениеПользователями.РазрешитьПечатьНепроведенныхДокументов(Проведен) Тогда

        Предупреждение("Недостаточно полномочий для печати непроведенного документа!");

        Возврат;

    КонецЕсли;



    Если Не РаботаСДиалогами.ПроверитьМодифицированность(ЭтотОбъект) Тогда

        Возврат;

    КонецЕсли;



    Если ИмяМакета = "Чек" Тогда

        Если Не ЗначениеЗаполнено(КассаККМ.Магазин) тогда

            Если Не ЗначениеЗаполнено(КассаККМ) Тогда

                НачалоСообщенияОбОшибке = "Не выбрана касса ККМ."

            Иначе

                НачалоСообщенияОбОшибке = "Выбранной кассе ККМ не назначен Магазин.";

            КонецЕсли;



            Предупреждение(НачалоСообщенияОбОшибке + Символы.ПС + "Печать чека невозможна.");

            Возврат;

        КонецЕсли;



        // Получить экземпляр документа на печать.

        ТабДокумент = ПечатьЧека();
    ИначеЕсли ИмяМакета = "ТоварныйЧекДляПД" Тогда
        Если Не ЗначениеЗаполнено(КассаККМ.Магазин) тогда
            Если Не ЗначениеЗаполнено(КассаККМ) Тогда
                НачалоСообщенияОбОшибке = "Не выбрана касса ККМ."
            Иначе
                НачалоСообщенияОбОшибке = "Выбранной кассе ККМ не назначен Магазин.";
            КонецЕсли;

            Предупреждение(НачалоСообщенияОбОшибке + Символы.ПС + "Печать чека невозможна.");
            Возврат;
        КонецЕсли;

        // Получить экземпляр документа на печать.
        ТабДокумент = ПечатьТоварногоЧекаДляПД();

    ИначеЕсли ИмяМакета = "КМ3" Тогда
        
        Если ЭтотОбъект.ВидОперации = Перечисления.ВидыОперацийЧекККМ.Возврат Тогда
            ТабДокумент = ПечатьКМ3();
            ПечататьВозвратныеЗаявления = Истина;
        Иначе
            Предупреждение("Данная печатная форма предназначена только для чеков возврата");
            Возврат;
        КонецЕсли;
        
    ИначеЕсли ТипЗнч(ИмяМакета) = Тип("ДвоичныеДанные") Тогда

        ТабДокумент = УниверсальныеМеханизмы.НапечататьВнешнююФорму(Ссылка, ИмяМакета);



        Если ТабДокумент = Неопределено Тогда

            Возврат;

        КонецЕсли;

    КонецЕсли;



    УниверсальныеМеханизмы.НапечататьДокумент(ТабДокумент, КоличествоЭкземпляров, НаПринтер, ОбщегоНазначения.СформироватьЗаголовокДокумента(ЭтотОбъект, ЭтотОбъект.Метаданные().Представление()), Ссылка,,,РежимРМК);

    
    Если ПечататьВозвратныеЗаявления Тогда
        ПечатьВозвратныеЗаявления();
    КонецЕсли;
    

КонецПроцедуры // Печать()


// Функция формирует табличный документ с печатной формой.

//

// Возвращаемое значение:

//  ТабличныйДокумент - печатная форма.

//

Функция ПечатьЧека()



    Запрос = Новый Запрос;
    Запрос.УстановитьПараметр("ТекущийДокумент", ЭтотОбъект.Ссылка);
    Запрос.УстановитьПараметр("Дата", Дата);

    Запрос.Текст = "
    |ВЫБРАТЬ
    |   ДокЧек.Номер,
    |   ДокЧек.Дата,
    |   ДокЧек.Дата КАК ДатаДокумента,
    |   ДокЧек.КассаККМ.Магазин КАК Магазин,
    |   ДокЧек.КассаККМ,
    |   ДокЧек.КассаККМ.Организация КАК Организация,
    |   ДокЧек.КассаККМ.Организация.ЮрФизЛицо КАК ЮрФизЛицо,
    |   ДокЧек.КассаККМ.Организация.ИндивидуальныйПредприниматель,
    |   ВЫБОР КОГДА ДокЧек.КассаККМ.Организация.ЮрФизЛицо = ЗНАЧЕНИЕ(Перечисление.ЮрФизЛицо.ЮрЛицо)
    |       ТОГДА ПРЕДСТАВЛЕНИЕ(ДокЧек.КассаККМ.Организация)
    |       ИНАЧЕ ""ИП "" +
    |           ВЫБОР   КОГДА ЕСТЬNULL(ФИОФизЛицСрезПоследнихИП.Фамилия, """") = """"
    |               ТОГДА """"
    |           ИНАЧЕ
    |               ФИОФизЛицСрезПоследнихИП.Фамилия + "" "" +
    |               ВЫБОР   КОГДА ЕСТЬNULL(ФИОФизЛицСрезПоследнихИП.Имя, """") = """"
    |                       ТОГДА """"
    |                       ИНАЧЕ ВЫРАЗИТЬ(ФИОФизЛицСрезПоследнихИП.Имя КАК СТРОКА(1)) + "". ""
    |               КОНЕЦ
    |               +
    |               ВЫБОР   КОГДА ЕСТЬNULL(ФИОФизЛицСрезПоследнихИП.Отчество, """") = """"
    |                       ТОГДА """"
    |                       ИНАЧЕ ВЫРАЗИТЬ(ФИОФизЛицСрезПоследнихИП.Отчество КАК СТРОКА(1)) + "".""
    |               КОНЕЦ
    |           КОНЕЦ
    |           + """"
    |   КОНЕЦ КАК НаименованиеОрганизации,
    |   ДокЧек.СуммаДокумента,
    |   ДокЧек.ВидОперации,
    |   ДокЧек.Товары.(
    |       НомерСтроки,
    |       Номенклатура,
    |       Номенклатура.Представление КАК Товар,
    |       Номенклатура.НаименованиеПолное КАК ТоварПолноеНаименование,
    |       Номенклатура.Код КАК Код,
    |       Номенклатура.Артикул КАК Артикул,
    |       Количество,
    |       ЕдиницаИзмерения.Представление КАК ЕдиницаИзмерения,
    |       Цена,
    |       Сумма,
    |       ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры
    |   ),
    |   ДокЧек.Оплата.(
    |       НомерСтроки,
    |       ВидОплаты,
    |       Сумма
    |   ),
    |   ВЫБОР   КОГДА ЕСТЬNULL(ФИОФизЛицСрезПоследних.Фамилия, """") = """"
    |               ТОГДА """"
    |           ИНАЧЕ
    |               ФИОФизЛицСрезПоследних.Фамилия + "" "" +
    |               ВЫБОР   КОГДА ЕСТЬNULL(ФИОФизЛицСрезПоследних.Имя, """") = """"
    |                       ТОГДА """"
    |                       ИНАЧЕ ВЫРАЗИТЬ(ФИОФизЛицСрезПоследних.Имя КАК СТРОКА(1)) + "". ""
    |               КОНЕЦ
    |               +
    |               ВЫБОР   КОГДА ЕСТЬNULL(ФИОФизЛицСрезПоследних.Отчество, """") = """"
    |                       ТОГДА """"
    |                       ИНАЧЕ ВЫРАЗИТЬ(ФИОФизЛицСрезПоследних.Отчество КАК СТРОКА(1)) + "".""
    |               КОНЕЦ
    |   КОНЕЦ КАК ФИО

    |ИЗ
    |   Документ.ЧекККМ КАК ДокЧек
    |ЛЕВОЕ СОЕДИНЕНИЕ
    |   Справочник.Пользователи КАК Пользователи
    |ПО
    |   Пользователи.Ссылка = ДокЧек.Ответственный
    |ЛЕВОЕ СОЕДИНЕНИЕ
    |   Справочник.ФизическиеЛица КАК ФизическиеЛица
    |ПО
    |   Пользователи.ФизЛицо = ФизическиеЛица.Ссылка
    |ЛЕВОЕ СОЕДИНЕНИЕ
    |   РегистрСведений.ФИОФизЛиц.СрезПоследних(&Дата) КАК ФИОФизЛицСрезПоследних
    |ПО
    |   ФизическиеЛица.Ссылка = ФИОФизЛицСрезПоследних.ФизЛицо
    |ЛЕВОЕ СОЕДИНЕНИЕ
    |   РегистрСведений.ФИОФизЛиц.СрезПоследних(&Дата) КАК ФИОФизЛицСрезПоследнихИП
    |ПО
    |   ДокЧек.КассаККМ.Организация = ФИОФизЛицСрезПоследнихИП.ФизЛицо

    |ГДЕ
    |   ДокЧек.Ссылка = &ТекущийДокумент

    |УПОРЯДОЧИТЬ ПО
    |   ДокЧек.Товары.НомерСтроки,
    |   ДокЧек.Оплата.НомерСтроки
    |";

    Шапка = Запрос.Выполнить().Выбрать();
    Шапка.Следующий();

    ТабДокумент = Новый ТабличныйДокумент;
    ТабДокумент.ИмяПараметровПечати = "ПАРАМЕТРЫ_ПЕЧАТИ_Чек_Накладная";

    Макет = ПолучитьМакет("Накладная");

    // Выводим шапку накладной.
    ОбластьМакета = Макет.ПолучитьОбласть("Заголовок");
    Если Шапка.ВидОперации = Перечисления.ВидыОперацийЧекККМ.Возврат Тогда
        ОбластьМакета.Параметры.ТекстЗаголовка = ОбщегоНазначения.СформироватьЗаголовокДокумента(Шапка, "Товарный чек (возврат)");
    Иначе
        ОбластьМакета.Параметры.ТекстЗаголовка = ОбщегоНазначения.СформироватьЗаголовокДокумента(Шапка, "Товарный чек");
    КонецЕсли;
    ТабДокумент.Вывести(ОбластьМакета);

    СведенияОПоставщике       = УправлениеКонтактнойИнформацией.СведенияОЮрФизЛице(Шапка.Организация,       Шапка.ДатаДокумента);
    
    ОбластьМакета = Макет.ПолучитьОбласть("Поставщик");
    
    Если Шапка.ЮрФизЛицо = Перечисления.ЮрФизЛицо.ЮрЛицо Тогда
        
        ОбластьМакета.Параметры.ПредставлениеПоставщика = ФормированиеПечатныхФорм.ОписаниеОрганизации(СведенияОПоставщике,"ПолноеНаименование,");
        
    Иначе
        
        ОбластьМакета.Параметры.ПредставлениеПоставщика = Шапка.НаименованиеОрганизации;
        
    КонецЕсли;
    
    ОбластьМакета.Параметры.Поставщик = Шапка.Организация;
    
    ТабДокумент.Вывести(ОбластьМакета);

    ОбластьМакета = Макет.ПолучитьОбласть("ИНН");
    ОбластьМакета.Параметры.ИНН = СведенияОПоставщике.ИНН;
    ТабДокумент.Вывести(ОбластьМакета);

    ОбластьМакета = Макет.ПолучитьОбласть("Магазин");
    ОбластьМакета.Параметры.ПредставлениеМагазина = Шапка.Магазин;
    ОбластьМакета.Параметры.Магазин = Шапка.Магазин;
    ТабДокумент.Вывести(ОбластьМакета);

    ЕстьСкидки = Ложь;
    ВыборкаСтрокТовары = Шапка.Товары.Выбрать();
    Пока ВыборкаСтрокТовары.Следующий() Цикл
        Если ВыборкаСтрокТовары.Цена * ВыборкаСтрокТовары.Количество - ВыборкаСтрокТовары.Сумма <> 0 Тогда
            ЕстьСкидки = Истина;
        КонецЕсли;
    КонецЦикла;

    ДопКолонка = Константы.ДополнительнаяКолонкаПечатныхФормДокументов.Получить();
    Если ДопКолонка = Перечисления.ДополнительнаяКолонкаПечатныхФормДокументов.Артикул Тогда
        ВыводитьКоды = Истина;
        Колонка = "Артикул";
    ИначеЕсли ДопКолонка = Перечисления.ДополнительнаяКолонкаПечатныхФормДокументов.Код Тогда
        ВыводитьКоды = Истина;
        Колонка = "Код";
    Иначе
        ВыводитьКоды = Ложь;
    КонецЕсли;

    ОбластьНомера = Макет.ПолучитьОбласть("ШапкаТаблицы|НомерСтроки");
    ОбластьКодов  = Макет.ПолучитьОбласть("ШапкаТаблицы|КолонкаКодов");
    ОбластьДанных = Макет.ПолучитьОбласть("ШапкаТаблицы|Данные");
    ОбластьСкидок = Макет.ПолучитьОбласть("ШапкаТаблицы|Скидка");
    ОбластьСуммы  = Макет.ПолучитьОбласть("ШапкаТаблицы|Сумма");

    ТабДокумент.Вывести(ОбластьНомера);
    Если ВыводитьКоды Тогда
        ОбластьКодов.Параметры.ИмяКолонкиКодов = Колонка;
        ТабДокумент.Присоединить(ОбластьКодов);
    КонецЕсли;
    ТабДокумент.Присоединить(ОбластьДанных);
    Если ЕстьСкидки Тогда
        ТабДокумент.Присоединить(ОбластьСкидок);
    КонецЕсли;
    ТабДокумент.Присоединить(ОбластьСуммы);

    ОбластьКолонкаТовар = Макет.Область("Товар");
    Если Не ВыводитьКоды Тогда
        ОбластьКолонкаТовар.ШиринаКолонки = ОбластьКолонкаТовар.ШиринаКолонки
                                          + Макет.Область("КолонкаКодов").ШиринаКолонки;
    КонецЕсли;
    Если Не ЕстьСкидки Тогда
        ОбластьКолонкаТовар.ШиринаКолонки = ОбластьКолонкаТовар.ШиринаКолонки
                                          + Макет.Область("СуммаБезСкидки").ШиринаКолонки
                                          + Макет.Область("СуммаСкидки").ШиринаКолонки;
    КонецЕсли;

    ОбластьНомера = Макет.ПолучитьОбласть("Строка|НомерСтроки");
    ОбластьКодов  = Макет.ПолучитьОбласть("Строка|КолонкаКодов");
    ОбластьДанных = Макет.ПолучитьОбласть("Строка|Данные");
    ОбластьСкидок = Макет.ПолучитьОбласть("Строка|Скидка");
    ОбластьСуммы  = Макет.ПолучитьОбласть("Строка|Сумма");

    Сумма          = 0;
    ВсегоСкидок    = 0;
    ВсегоБезСкидок = 0;

    ВыборкаСтрокТовары = Шапка.Товары.Выбрать();
    Пока ВыборкаСтрокТовары.Следующий() Цикл
        Если НЕ ЗначениеЗаполнено(ВыборкаСтрокТовары.Номенклатура) Тогда
            Сообщить("В одной из строк не заполнено значение номенклатуры - строка при печати пропущена.", СтатусСообщения.Важное);
            Продолжить;
        КонецЕсли;

        ОбластьНомера.Параметры.Заполнить(ВыборкаСтрокТовары);
        ТабДокумент.Вывести(ОбластьНомера);

        Если ВыводитьКоды Тогда
            Если Колонка = "Артикул" Тогда
                ОбластьКодов.Параметры.Артикул = ВыборкаСтрокТовары.Артикул;
            Иначе
                ОбластьКодов.Параметры.Артикул = ВыборкаСтрокТовары.Код;
            КонецЕсли;
            ТабДокумент.Присоединить(ОбластьКодов);
        КонецЕсли;

        ОбластьДанных.Параметры.Заполнить(ВыборкаСтрокТовары);
        ОбластьДанных.Параметры.Товар = ?(Не ЗначениеЗаполнено(ВыборкаСтрокТовары.ТоварПолноеНаименование),
                                          ВыборкаСтрокТовары.Товар,
                                          ВыборкаСтрокТовары.ТоварПолноеНаименование)
                                      + УниверсальныеМеханизмы.ПредставлениеХарактеристик(ВыборкаСтрокТовары);
        ТабДокумент.Присоединить(ОбластьДанных);

        Скидка = ВыборкаСтрокТовары.Цена * ВыборкаСтрокТовары.Количество - ВыборкаСтрокТовары.Сумма;
        Если ЕстьСкидки Тогда
            ОбластьСкидок.Параметры.Скидка         = Скидка;
            ОбластьСкидок.Параметры.СуммаБезСкидки = ВыборкаСтрокТовары.Сумма + Скидка;
            ТабДокумент.Присоединить(ОбластьСкидок);
        КонецЕсли;

        ОбластьСуммы.Параметры.Заполнить(ВыборкаСтрокТовары);
        ТабДокумент.Присоединить(ОбластьСуммы);
        Сумма          = Сумма + ВыборкаСтрокТовары.Сумма;
        ВсегоСкидок    = ВсегоСкидок + Скидка;
        ВсегоБезСкидок = Сумма + ВсегоСкидок;
    КонецЦикла;

    // Вывести Итого.
    ОбластьНомера = Макет.ПолучитьОбласть("Итого|НомерСтроки");
    ОбластьКодов  = Макет.ПолучитьОбласть("Итого|КолонкаКодов");
    ОбластьДанных = Макет.ПолучитьОбласть("Итого|Данные");
    ОбластьСкидок = Макет.ПолучитьОбласть("Итого|Скидка");
    ОбластьСуммы  = Макет.ПолучитьОбласть("Итого|Сумма");

    ТабДокумент.Вывести(ОбластьНомера);
    Если ВыводитьКоды Тогда
        ТабДокумент.Присоединить(ОбластьКодов);
    КонецЕсли;
    ТабДокумент.Присоединить(ОбластьДанных);
    Если ЕстьСкидки Тогда
        ОбластьСкидок.Параметры.ВсегоСкидок    = ВсегоСкидок;
        ОбластьСкидок.Параметры.ВсегоБезСкидок = ВсегоБезСкидок;
        ТабДокумент.Присоединить(ОбластьСкидок);
    КонецЕсли;
    ОбластьСуммы.Параметры.Всего = Сумма;
    ТабДокумент.Присоединить(ОбластьСуммы);

    // Вывести Сумму прописью.
    ОбластьМакета = Макет.ПолучитьОбласть("СуммаПрописью");
    ОбластьМакета.Параметры.ИтоговаяСтрока = "Всего наименований " + ВыборкаСтрокТовары.Количество()
                                           + ", на сумму " + ОбщегоНазначения.ФорматСумм(Шапка.СуммаДокумента);
    ОбластьМакета.Параметры.СуммаПрописью  = ОбщегоНазначения.СформироватьСуммуПрописью(Шапка.СуммаДокумента);
    ТабДокумент.Вывести(ОбластьМакета);

    // Вывести Оплату и Сдачу.
    СуммаОплат = 0;
    СуммаБезналичныхОплат = 0;
    СписокОплат = Новый Соответствие();

    ВыборкаОплат = Шапка.Оплата.Выбрать();
    Пока ВыборкаОплат.Следующий() Цикл
        Если Шапка.ВидОперации = Перечисления.ВидыОперацийЧекККМ.Возврат
           И ВыборкаОплат.ВидОплаты.ТипОплаты <> Перечисления.ТипыОплатЧекаККМ.Наличные Тогда
            СуммаБезналичныхОплат = СуммаБезналичныхОплат + ВыборкаОплат.Сумма;
        КонецЕсли;

        ЗаписьОплаты = СписокОплат.Получить(Строка(ВыборкаОплат.ВидОплаты.ТипОплаты));
        Если ЗаписьОплаты = Неопределено Тогда
            СписокОплат.Вставить(Строка(ВыборкаОплат.ВидОплаты.ТипОплаты), ВыборкаОплат.Сумма);
        Иначе
            СписокОплат.Вставить(Строка(ВыборкаОплат.ВидОплаты.ТипОплаты), ЗаписьОплаты + ВыборкаОплат.Сумма);
        КонецЕсли;
        СуммаОплат = СуммаОплат + ВыборкаОплат.Сумма;
    КонецЦикла;

    //Отдельная подготовка наличной оплаты для чека возврата
    Если Шапка.ВидОперации = Перечисления.ВидыОперацийЧекККМ.Возврат Тогда
        СписокОплат.Вставить(Строка(Перечисления.ТипыОплатЧекаККМ.Наличные), Шапка.СуммаДокумента - СуммаБезналичныхОплат);
    КонецЕсли;

    ОбластьМакета = Макет.ПолучитьОбласть("Оплата");
    ОплатаДобавлена = Ложь;
    Для Каждого ЗнПеречисления Из Перечисления.ТипыОплатЧекаККМ Цикл
        ЗаписьОплаты = СписокОплат.Получить(Строка(ЗнПеречисления));
        Если ЗаписьОплаты <> Неопределено Тогда
            ОбластьМакета.Параметры.Оплата = ?(ОплатаДобавлена, ОбластьМакета.Параметры.Оплата + Символы.ПС, "")
                                           + Строка(ЗнПеречисления) + ": "  + Формат(ЗаписьОплаты, "ЧЦ=15; ЧДЦ=2; ЧРД=.; ЧН=; ЧГ=0");
            ОплатаДобавлена = Истина;
        КонецЕсли;
    КонецЦикла;
    Если Шапка.ВидОперации = Перечисления.ВидыОперацийЧекККМ.Продажа Тогда
        ОбластьМакета.Параметры.Сдача = Формат(СуммаОплат - Шапка.СуммаДокумента, "ЧЦ=15; ЧДЦ=2; ЧРД=.; ЧН=; ЧГ=0");
    Иначе
        ОбластьМакета.Параметры.Сдача = "0.00";
    КонецЕсли;
    ТабДокумент.Вывести(ОбластьМакета);

    // Вывести подписи.
    ОбластьМакета = Макет.ПолучитьОбласть("Подписи");
    ОбластьМакета.Параметры.Заполнить(Шапка);
    ТабДокумент.Вывести(ОбластьМакета);

    Возврат ТабДокумент;



КонецФункции // ПечатьЧека()

// Функция формирует табличный документ с печатной формой узкого чека для печати на принтерах с чековой лентой.
Функция ПечатьТоварногоЧекаДляПД()

    ДокументЧекККМ  = Новый ТабличныйДокумент();
    МассивСтрокЧека = Новый Массив();

    // Получение макета
    МакетЧекаККМ             = Документы.ЧекККМ.ПолучитьМакет("ТоварныйЧекДляПД");
    ОбластьШапкаЧека         = МакетЧекаККМ.ПолучитьОбласть("ШапкаЧека|_"         + КассаККМ.ШиринаЛенты);
    ОбластьТелоЧека          = МакетЧекаККМ.ПолучитьОбласть("ТелоЧека|_"          + КассаККМ.ШиринаЛенты);
    ОбластьТелоЧекаСкидка    = МакетЧекаККМ.ПолучитьОбласть("ТелоЧекаСкидка|_"    + КассаККМ.ШиринаЛенты);
    ОбластьТелоЧекаОтступ    = МакетЧекаККМ.ПолучитьОбласть("ТелоЧекаОтступ|_"    + КассаККМ.ШиринаЛенты);
    ОбластьПодвалЧека        = МакетЧекаККМ.ПолучитьОбласть("ПодвалЧека|_"        + КассаККМ.ШиринаЛенты);
    ОбластьПодвалЧекаОплата  = МакетЧекаККМ.ПолучитьОбласть("ПодвалЧекаОплата|_"  + КассаККМ.ШиринаЛенты);
    ОбластьПодвалЧекаОстаток = МакетЧекаККМ.ПолучитьОбласть("ПодвалЧекаОстаток|_" + КассаККМ.ШиринаЛенты);

    // Получение данных документа
    Запрос = Новый Запрос;
    Запрос.УстановитьПараметр("ТекущийДокумент", ЭтотОбъект.Ссылка);
    Запрос.УстановитьПараметр("Дата", Дата);

    Запрос.Текст = "
    |ВЫБРАТЬ
    |   ДокЧек.Номер,
    |   ДокЧек.Дата,
    |   ДокЧек.КассаККМ,
    |   ДокЧек.КассаККМ.Организация КАК Организация,
    |   ВЫБОР КОГДА ДокЧек.КассаККМ.Организация.ЮрФизЛицо = ЗНАЧЕНИЕ(Перечисление.ЮрФизЛицо.ЮрЛицо)
    |       ТОГДА ПРЕДСТАВЛЕНИЕ(ДокЧек.КассаККМ.Организация)
    |       ИНАЧЕ ""ИП "" +
    |           ВЫБОР   КОГДА ЕСТЬNULL(ФИОФизЛицСрезПоследнихИП.Фамилия, """") = """"
    |               ТОГДА """"
    |           ИНАЧЕ
    |               ФИОФизЛицСрезПоследнихИП.Фамилия + "" "" +
    |               ВЫБОР   КОГДА ЕСТЬNULL(ФИОФизЛицСрезПоследнихИП.Имя, """") = """"
    |                       ТОГДА """"
    |                       ИНАЧЕ ВЫРАЗИТЬ(ФИОФизЛицСрезПоследнихИП.Имя КАК СТРОКА(1)) + "". ""
    |               КОНЕЦ
    |               +
    |               ВЫБОР   КОГДА ЕСТЬNULL(ФИОФизЛицСрезПоследнихИП.Отчество, """") = """"
    |                       ТОГДА """"
    |                       ИНАЧЕ ВЫРАЗИТЬ(ФИОФизЛицСрезПоследнихИП.Отчество КАК СТРОКА(1)) + "".""
    |               КОНЕЦ
    |           КОНЕЦ
    |           + """"
    |   КОНЕЦ КАК НаименованиеОрганизации,
    |   ДокЧек.СуммаДокумента,
    |   ДокЧек.ВидОперации,
    |   ДокЧек.Товары.(
    |       НомерСтроки,
    |       Номенклатура,
    |       Номенклатура.Представление КАК Товар,
    |       Номенклатура.НаименованиеПолное КАК ТоварПолноеНаименование,
    |       Номенклатура.Код КАК Код,
    |       Номенклатура.Артикул КАК Артикул,
    |       Количество,
    |       ЕдиницаИзмерения.Представление КАК ЕдиницаИзмерения,
    |       Цена,
    |       Сумма,
    |       ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры
    |   ),
    |   ДокЧек.Оплата.(
    |       НомерСтроки,
    |       ВидОплаты,
    |       Сумма
    |   ),
    |   ВЫБОР   КОГДА ЕСТЬNULL(ФИОФизЛицСрезПоследних.Фамилия, """") = """"
    |               ТОГДА """"
    |           ИНАЧЕ
    |               ФИОФизЛицСрезПоследних.Фамилия + "" "" +
    |               ВЫБОР   КОГДА ЕСТЬNULL(ФИОФизЛицСрезПоследних.Имя, """") = """"
    |                       ТОГДА """"
    |                       ИНАЧЕ ВЫРАЗИТЬ(ФИОФизЛицСрезПоследних.Имя КАК СТРОКА(1)) + "". ""
    |               КОНЕЦ
    |               +
    |               ВЫБОР   КОГДА ЕСТЬNULL(ФИОФизЛицСрезПоследних.Отчество, """") = """"
    |                       ТОГДА """"
    |                       ИНАЧЕ ВЫРАЗИТЬ(ФИОФизЛицСрезПоследних.Отчество КАК СТРОКА(1)) + "".""
    |               КОНЕЦ
    |   КОНЕЦ КАК ФИО

    |ИЗ
    |   Документ.ЧекККМ КАК ДокЧек
    |ЛЕВОЕ СОЕДИНЕНИЕ
    |   Справочник.Пользователи КАК Пользователи
    |ПО
    |   Пользователи.Ссылка = ДокЧек.Ответственный
    |ЛЕВОЕ СОЕДИНЕНИЕ
    |   Справочник.ФизическиеЛица КАК ФизическиеЛица
    |ПО
    |   Пользователи.ФизЛицо = ФизическиеЛица.Ссылка
    |ЛЕВОЕ СОЕДИНЕНИЕ
    |   РегистрСведений.ФИОФизЛиц.СрезПоследних(&Дата) КАК ФИОФизЛицСрезПоследних
    |ПО
    |   ФизическиеЛица.Ссылка = ФИОФизЛицСрезПоследних.ФизЛицо
    |ЛЕВОЕ СОЕДИНЕНИЕ
    |   РегистрСведений.ФИОФизЛиц.СрезПоследних(&Дата) КАК ФИОФизЛицСрезПоследнихИП
    |ПО
    |   ДокЧек.КассаККМ.Организация = ФИОФизЛицСрезПоследнихИП.ФизЛицо

    |ГДЕ
    |   ДокЧек.Ссылка = &ТекущийДокумент

    |УПОРЯДОЧИТЬ ПО
    |   ДокЧек.Товары.НомерСтроки,
    |   ДокЧек.Оплата.НомерСтроки
    |";

    РезультатЗапроса = Запрос.Выполнить();
    Если РезультатЗапроса.Пустой() Тогда
        Ответ     = "Пустой чек не может быть пробит на устройстве!";
        Отказ     = Истина;
        Результат = Ложь;
        Возврат Результат;
    КонецЕсли;

    Выборка = РезультатЗапроса.Выбрать();
    Выборка.Следующий();

    // Формирование чека
    // ШАПКА
    Если Выборка.ВидОперации = Перечисления.ВидыОперацийЧекККМ.Возврат Тогда
        ОбластьШапкаЧека.Параметры.Заголовок = ОбщегоНазначения.СформироватьЗаголовокДокумента(Выборка, "Чек (возврат)");
    Иначе
        ОбластьШапкаЧека.Параметры.Заголовок = ОбщегоНазначения.СформироватьЗаголовокДокумента(Выборка, "Чек");
    КонецЕсли;
    ОбластьШапкаЧека.Параметры.Организация = Строка(Выборка.НаименованиеОрганизации);
    ОбластьШапкаЧека.Параметры.ИНН         = "ИНН: " + Выборка.Организация.ИНН;
    ДокументЧекККМ.Вывести(ОбластьШапкаЧека);


    // ТЕЛО
    ВыборкаТоваров = Выборка.Товары.Выбрать();
    Пока ВыборкаТоваров.Следующий() Цикл
        ОбластьТелоЧека.Параметры.НаименованиеТовара = ВыборкаТоваров.ТоварПолноеНаименование
                                                     + "(" + ВыборкаТоваров.ЕдиницаИзмерения + ")";
        ОбластьТелоЧека.Параметры.КоличествоЦена     = Формат(ВыборкаТоваров.Количество, "ЧЦ=17; ЧДЦ=3; ЧРД=.; ЧН=; ЧГ=0")
                                                     + " х "
                                                     + Формат(ВыборкаТоваров.Цена, "ЧЦ=15; ЧДЦ=2; ЧРД=.; ЧН=; ЧГ=0");

        КонечнаяСкидка = ВыборкаТоваров.Количество * ВыборкаТоваров.Цена - ВыборкаТоваров.Сумма;
        ДокументЧекККМ.Вывести(ОбластьТелоЧека);

        Если КонечнаяСкидка <> 0 Тогда
            ОбластьТелоЧекаСкидка.Параметры.ЗагСкидка = ?(КонечнаяСкидка > 0, "Скидка:", "Надбавка:");
            ОбластьТелоЧекаСкидка.Параметры.Скидка    = Формат(?(КонечнаяСкидка > 0, КонечнаяСкидка, -КонечнаяСкидка), "ЧЦ=15; ЧДЦ=2; ЧРД=.; ЧН=; ЧГ=0");
            ДокументЧекККМ.Вывести(ОбластьТелоЧекаСкидка);
        КонецЕсли;

        ДокументЧекККМ.Вывести(ОбластьТелоЧекаОтступ);
    КонецЦикла;
    //ДокументЧекККМ.УдалитьСтроку(ДокументЧекККМ.КоличествоСтрок());

    // ПОДВАЛ
    ОбластьПодвалЧека.Параметры.Итог = Формат(Выборка.СуммаДокумента, "ЧЦ=15; ЧДЦ=2; ЧРД=.; ЧН=; ЧГ=0");
    ДокументЧекККМ.Вывести(ОбластьПодвалЧека);

    СуммаОплат = 0;
    СуммаБезналичныхОплат = 0;
    СписокОплат = Новый Соответствие();

    ВыборкаОплат = Выборка.Оплата.Выбрать();
    Пока ВыборкаОплат.Следующий() Цикл
        Если Выборка.ВидОперации = Перечисления.ВидыОперацийЧекККМ.Возврат
           И ВыборкаОплат.ВидОплаты.ТипОплаты <> Перечисления.ТипыОплатЧекаККМ.Наличные Тогда
            СуммаБезналичныхОплат = СуммаБезналичныхОплат + ВыборкаОплат.Сумма;
        КонецЕсли;

        ЗаписьОплаты = СписокОплат.Получить(Строка(ВыборкаОплат.ВидОплаты.ТипОплаты));
        Если ЗаписьОплаты = Неопределено Тогда
            СписокОплат.Вставить(Строка(ВыборкаОплат.ВидОплаты.ТипОплаты), ВыборкаОплат.Сумма);
        Иначе
            СписокОплат.Вставить(Строка(ВыборкаОплат.ВидОплаты.ТипОплаты), ЗаписьОплаты + ВыборкаОплат.Сумма);
        КонецЕсли;
        СуммаОплат = СуммаОплат + ВыборкаОплат.Сумма;
    КонецЦикла;

    //Отдельная подготовка наличной оплаты для чека возврата
    Если Выборка.ВидОперации = Перечисления.ВидыОперацийЧекККМ.Возврат Тогда
        СписокОплат.Вставить(Строка(Перечисления.ТипыОплатЧекаККМ.Наличные), Выборка.СуммаДокумента - СуммаБезналичныхОплат);
    КонецЕсли;

    ОплатаДобавлена = Ложь;
    Для Каждого ЗнПеречисления Из Перечисления.ТипыОплатЧекаККМ Цикл
        ЗаписьОплаты = СписокОплат.Получить(Строка(ЗнПеречисления));
        Если ЗаписьОплаты <> Неопределено Тогда
            ОбластьПодвалЧекаОплата.Параметры.ТипОплаты = Строка(ЗнПеречисления) + ":";
            ОбластьПодвалЧекаОплата.Параметры.Оплата = Формат(ЗаписьОплаты, "ЧЦ=15; ЧДЦ=2; ЧРД=.; ЧН=; ЧГ=0");
            //ОплатаДобавлена = Истина;
            ДокументЧекККМ.Вывести(ОбластьПодвалЧекаОплата);
        КонецЕсли;
    КонецЦикла;

    Если Выборка.ВидОперации <> Перечисления.ВидыОперацийЧекККМ.Возврат Тогда
        ОбластьПодвалЧекаОстаток.Параметры.Сдача = Формат(СуммаОплат - Выборка.СуммаДокумента, "ЧЦ=15; ЧДЦ=2; ЧРД=.; ЧН=; ЧГ=0");
    КонецЕсли;

    ОбластьПодвалЧекаОстаток.Параметры.Сотрудник = Выборка.ФИО;

    ДокументЧекККМ.Вывести(ОбластьПодвалЧекаОстаток);

    Возврат ДокументЧекККМ;

КонецФункции


// Функция формирует табличный документ с печатной формой КМ3
//
// Возвращаемое значение:
//  ТабличныйДокумент - печатная форма.
//
Функция ПечатьКМ3()
    

    Запрос = Новый Запрос;

    Запрос.УстановитьПараметр("ТекущийДокумент", ЭтотОбъект.Ссылка);



    Запрос.Текст =

    "ВЫБРАТЬ

    |   ДокЧек.Номер КАК Номер,

    |   ДокЧек.Дата  КАК ДатаДокумента,

    |   ДокЧек.КассаККМ,

    |   ДокЧек.КассаККМ.Представление                КАК Покупатель,
    |   ДокЧек.Ответственный.ФизЛицо                 КАК КассирККМ,

    |   ДокЧек.КассаККМ.Организация                  КАК Организация,
    |   ДокЧек.КассаККМ.Организация                  КАК Руководители,

    |   ДокЧек.КассаККМ.Организация.Представление    КАК Поставщик,
    |   ДокЧек.КассаККМ.СерийныйНомер                КАК СерийныйНомерККМ,
    |   ДокЧек.КассаККМ.РегистрационныйНомер         КАК РегистрационныйНомерККМ,
    |   ДокЧек.ЧекККМПродажа.НомерЧекаККМ            КАК НомерЧека,
    |   ДокЧек.СуммаДокумента                        КАК СуммаДокумента

    |ИЗ

    |   Документ.ЧекККМ КАК ДокЧек

    |ГДЕ

    |   ДокЧек.Ссылка = &ТекущийДокумент

    |";

    
    Шапка = Запрос.Выполнить().Выбрать();

    Шапка.Следующий();

    
    ЗапросККМ = Новый Запрос;

    ЗапросККМ.УстановитьПараметр("КассаККМ", Шапка.КассаККМ);

    

    ЗапросККМ.Текст = "ВЫБРАТЬ

                      | регТорговоеОборудование.Модель.Модель КАК ПредставлениеККМ

                      |ИЗ

                      | РегистрСведений.ТорговоеОборудование КАК регТорговоеОборудование

                      |ГДЕ

                      | регТорговоеОборудование.КассаККМ = &КассаККМ";

    
    РезультатККМ = ЗапросККМ.Выполнить().Выбрать();

    

    ТабДокумент = Новый ТабличныйДокумент;

    ТабДокумент.ИмяПараметровПечати = "ПАРАМЕТРЫ_ПЕЧАТИ_Чек_КМ3";



    Макет         = ПолучитьОбщийМакет("КМ3");

    ОбластьМакета = Макет.ПолучитьОбласть("ОбластьАкта");
    
    Если РезультатККМ.Следующий() Тогда

        ОбластьМакета.Параметры.Заполнить(РезультатККМ);

    КонецЕсли;
    

    ОбластьМакета.Параметры.Заполнить(Шапка);
    
    СведенияОбОрганизации = УправлениеКонтактнойИнформацией.СведенияОЮрФизЛице(Шапка.Организация, Шапка.ДатаДокумента);
    

    ОбластьМакета.Параметры.ПредставлениеОрганизации = ФормированиеПечатныхФорм.ОписаниеОрганизации(СведенияОбОрганизации, "ПолноеНаименование,ИНН,ЮридическийАдрес,Телефоны");

    ОбластьМакета.Параметры.СуммаПрописью            = ОбщегоНазначения.СформироватьСуммуПрописью(Шапка.СуммаДокумента);

    ОбластьМакета.Параметры.НомерДокумента           = "";


    ОбластьМакета.Параметры.ОрганизацияПоОКПО     = СведенияОбОрганизации.КодПоОКПО;
    ОбластьМакета.Параметры.ОрганизацияИНН        = СведенияОбОрганизации.ИНН;

    ОбластьМакета.Параметры.ВидДеятельностиПоОКДП = "";

    
    Руководители          = ФормированиеПечатныхФорм.ОтветственныеЛицаОрганизаций(Шапка.Руководители, Шапка.ДатаДокумента);

    Руководитель          = Руководители.Руководитель;

    СтаршийКассир         = Руководители.Кассир;

    ДолжностьРуководителя = Руководители.РуководительДолжность;
    
    Если ЗначениеЗаполнено(Шапка.КассирККМ) Тогда
        СтруктураФИОКассираККМ  = ФормированиеПечатныхФорм.ФамилияИмяОтчество(Шапка.КассирККМ, Шапка.ДатаДокумента);
        ФИОКассираОперациониста = ФормированиеПечатныхФорм.ФамилияИнициалыФизЛица(Ложь,
                                   СтруктураФИОКассираККМ.Фамилия,
                                   СтруктураФИОКассираККМ.Имя,
                                   СтруктураФИОКассираККМ.Отчество);
    КонецЕсли;
    

    ОбластьМакета.Параметры.ФИОКассираОрганизации   = СтаршийКассир;

    ОбластьМакета.Параметры.ФИОРуководителя         = Руководитель;
    ОбластьМакета.Параметры.ФИОКассираОперациониста = ФИОКассираОперациониста;

    ОбластьМакета.Параметры.ДолжностьРуководителя   = ДолжностьРуководителя;
    
    ТабДокумент.Вывести(ОбластьМакета);



    Возврат ТабДокумент;

    
КонецФункции


// Функция осуществляет печать чека.
//
// Параметры:
//  Идентификатор                  - <Строка>
//                                 - Идентификатор фискального регистратора.
//
//  НомерЧека                      - <Число>
//                                 - Выходной параметр; номер чека.
//
//  НомерСмены                     - <Число>
//                                 - Выходной параметр; номер смены.
//
//  ОписаниеЧека                   - <ТаблицаЗначений>
//                                 - Описание чека. Таблица имеет следующие колонки:
//                                     Наименование - <Строка>
//                                                  - Наименование позиции.
//                                     НомерСекции  - <Число>
//                                                  - Номер секции.
//                                     Цена         - <Число>
//                                                  - Цена за единицу.
//                                     Количество   - <Число>
//                                                  - Количество единиц.
//                                     Скидка       - <Число>
//                                                  - Процент скидки (>0) или наценки (<0).
//
//  СуммаНал                       - <Число>
//                                 - Сумма наличными (принятая, или выданная).
//
//  СуммаБезнал                    - <Число>
//                                 - Сумма безналичными (принятая, или выданная).
//
//  ПризнакВозврата                - <Булево>
//                                 - Признак необходимости печати чека на возврат.
//
// Возвращаемое значение:
//  <ПеречислениеСсылка.ТООшибки*> - Результат работы функции
//
Функция ПечатьЧекаККМ(Идентификатор, НомерЧека, НомерСмены,
                      ОписаниеЧека, СуммаНал, СуммаБезнал, ПризнакВозврата)

    СтруктрураШаблона = КассаККМ.ШаблонЧекККМ.Шаблон.Получить();
    Если СтруктрураШаблона <> Неопределено Тогда
        
        Параметры = Новый Структура();
        Параметры.Вставить("СхемаКомпоновкиДанных", Неопределено);
        Параметры.Вставить("КомпоновщикМакета", Неопределено);
        Параметры.Вставить("КэшМакетов", Неопределено);
        
        СтруктрураШаблона.Вставить("Шаблон", ПроцедурыПечатиФискальныхЧеков.ПолучитьМакетФискальногоЧекаДокументаЧекККМ(Ссылка, СтруктрураШаблона.Шаблон, СтруктрураШаблона.ШиринаЧека, Параметры));
        СтруктрураШаблона.Вставить("СоставнойМассив", Новый Массив);
        СтруктрураШаблона.Вставить("Идентификатор", Идентификатор);
        
    КонецЕсли;
    
    Результат = ПолучитьСерверТО().ОткрытьЧек(Идентификатор, "", ПризнакВозврата, НомерЧека, НомерСмены);
    Если НЕ ЗначениеЗаполнено(Результат) Тогда
        
        Результат = ПроцедурыПечатиФискальныхЧеков.НапечататьСтроки(СтруктрураШаблона, "Шапка");
        Если ЗначениеЗаполнено(Результат) Тогда
            Возврат Результат;
        КонецЕсли;
        
        Позиция = Неопределено;
        Для Каждого Позиция Из ОписаниеЧека Цикл
            
            Результат = ПроцедурыПечатиФискальныхЧеков.НапечататьСтроки(СтруктрураШаблона, "ТелоШапка_"+ОписаниеЧека.Индекс(Позиция));
            Если ЗначениеЗаполнено(Результат) Тогда
                Возврат Результат;
            КонецЕсли;
            
            ЗначениеСкидки = Позиция.Количество * Позиция.Цена * Позиция.Скидка * 0.01;
            СуммаСоСкидкой1С = Окр(Позиция.Количество * Позиция.Цена - ЗначениеСкидки, 2);
            СуммаСоСкидкойФР = Окр(Позиция.Количество * Позиция.Цена - Окр(ЗначениеСкидки, 2), 2);
            
            Если НЕ (СтруктрураШаблона <> Неопределено И СтруктрураШаблона.ОднаФискальнаяСтрока) Тогда
                Если СуммаСоСкидкой1С = СуммаСоСкидкойФР Тогда
                    
                    СтрокаЧека = Новый Структура("Наименование, Количество, Цена, Скидка, НомерСекции, СтавкаНДС");
                    СтрокаЧека.Наименование = ?(СтруктрураШаблона = Неопределено,Позиция.Наименование,"");
                    СтрокаЧека.Количество   = Позиция.Количество;
                    СтрокаЧека.Цена         = Позиция.Цена;
                    СтрокаЧека.Скидка       = Позиция.Скидка;
                    СтрокаЧека.НомерСекции  = Позиция.НомерСекции;
                    СтрокаЧека.СтавкаНДС    = Позиция.СтавкаНДС;
                    Результат = ПолучитьСерверТО().ПечатьСтрокиЧека(Идентификатор, СтрокаЧека);
                    
                Иначе
                    
                    СтрокаЧека = Новый Структура("Наименование, Количество, Цена, Скидка, НомерСекции, СтавкаНДС");
                    СтрокаЧека.Наименование = ?(СтруктрураШаблона = Неопределено,Позиция.Наименование,"");
                    СтрокаЧека.Количество   = 1;
                    СтрокаЧека.Цена         = СуммаСоСкидкой1С;
                    СтрокаЧека.Скидка       = 0;
                    СтрокаЧека.НомерСекции  = Позиция.НомерСекции;
                    СтрокаЧека.СтавкаНДС    = Позиция.СтавкаНДС;
                    Результат = ПолучитьСерверТО().ПечатьСтрокиЧека(Идентификатор, СтрокаЧека);
                    
                КонецЕсли;
            КонецЕсли;
            
            Если ЗначениеЗаполнено(Результат) Тогда
                Возврат Результат;
            КонецЕсли;
            
            Результат = ПроцедурыПечатиФискальныхЧеков.НапечататьСтроки(СтруктрураШаблона, "ТелоПодвал_"+ОписаниеЧека.Индекс(Позиция));
            Если ЗначениеЗаполнено(Результат) Тогда
                Возврат Результат;
            КонецЕсли;
            
        КонецЦикла;
        
        Результат = ПроцедурыПечатиФискальныхЧеков.НапечататьСтроки(СтруктрураШаблона, "Подвал");
        Если ЗначениеЗаполнено(Результат) Тогда
            Возврат Результат;
        КонецЕсли;
        
        Если НЕ ЗначениеЗаполнено(Результат) Тогда
            Если СтруктрураШаблона <> Неопределено И СтруктрураШаблона.ОднаФискальнаяСтрока Тогда
                
                МассивСтрокДляПечати = ПроцедурыПечатиФискальныхЧеков.ПреобразоватьМассивСоответствийВМассивТекстовыхСтрок(СтруктрураШаблона.СоставнойМассив);
                Результат = ПОлучитьСерверТО().ПечатьТекста(Идентификатор, МассивСтрокДляПечати, СтруктрураШаблона.ШиринаЧека);
                
                Если ЗначениеЗаполнено(Результат) Тогда
                    Возврат Результат;
                КонецЕсли;
                
                СтрокаЧека = Новый Структура("Наименование, Количество, Цена, Скидка, НомерСекции, СтавкаНДС");
                СтрокаЧека.Наименование = "Всего:";
                СтрокаЧека.Количество   = 1;
                СтрокаЧека.Цена         = Товары.Итог("Сумма");
                СтрокаЧека.Скидка       = 0;
                СтрокаЧека.СтавкаНДС    = 0;
                СтрокаЧека.НомерСекции  = Позиция.НомерСекции;
                Результат = ПолучитьСерверТО().ПечатьСтрокиЧека(Идентификатор, СтрокаЧека);
                
            КонецЕсли;
        КонецЕсли;
        
        Если НЕ ЗначениеЗаполнено(Результат) Тогда
            Результат = ПолучитьСерверТО().ЗакрытьЧек(Идентификатор, СуммаНал, СуммаБезнал);
        КонецЕсли;
        
    КонецЕсли;

    Возврат Результат;

КонецФункции // ПечатьЧека()


Процедура ПечатьВозвратныеЗаявления();
    
    Обработка     = Обработки.ВозвратТоваровОтРозничногоПокупателя.Создать();
    Обработка.Товары.Загрузить(ЭтотОбъект.Товары.Выгрузить());
    
    Для Каждого СтрокаТабличнойЧасти Из Обработка.Товары Цикл
        СтрокаТабличнойЧасти.ДокументПродажи = ЭтотОбъект.ЧекККМПродажа;
    КонецЦикла;
    
    Обработка.Касса                 = ЭтотОбъект.КассаККМ;
    Обработка.ЧекНомер              = ЭтотОбъект.ЧекККМПродажа.НомерЧекаККМ;
    Обработка.ЧекДата               = ЭтотОбъект.ЧекККМПродажа.Дата;
    Обработка.ХозяйственнаяОперация = ЭтотОбъект.ХозяйственнаяОперация;
    
    ФормаВозврата = Обработка.ПолучитьФорму();
    
    КомманднаяПанельКнопки = ФормаВозврата.ЭлементыФормы.ОсновныеДействияФормы.Кнопки;
    КомманднаяПанельКнопки.Удалить(КомманднаяПанельКнопки.Найти("ОсновныеДействияФормыВыполнить"));
    КомманднаяПанельКнопки.Удалить(КомманднаяПанельКнопки.Найти("Разделитель"));
    КомманднаяПанельКнопки.Печать.Кнопки.Удалить(КомманднаяПанельКнопки.Печать.Кнопки.Найти("ПечатьРКО"));
    КомманднаяПанельКнопки.Печать.Кнопки.Удалить(КомманднаяПанельКнопки.Печать.Кнопки.Найти("Печать"));
    
    ФормаВозврата.ЭлементыФормы.КоманднаяПанельТовары.Доступность = Ложь;
    ФормаВозврата.ЭлементыФормы.Товары.Доступность                = Ложь;
    ФормаВозврата.ЭлементыФормы.Контрагент.Доступность            = Ложь;
    ФормаВозврата.ЭлементыФормы.Склад.Доступность                 = Ложь;
    ФормаВозврата.ЭлементыФормы.Основание.Доступность             = Ложь;
    ФормаВозврата.ЭлементыФормы.ХозяйственнаяОперация.Доступность = Ложь;
    
    ФормаВозврата.Открыть();
    
КонецПроцедуры

// Функция осуществляет проведение документа и печать чека на ФР.
//
// Параметры:
//  Ответ    - <Строка>
//           - Выходной параметр; описание произошедшей ошибки.
//
//  Отказ    - <Булево>
//           - Выходной параметр; признак отказа от выполнения операции.
//
// Возвращаемое значение:
//  <Булево> - Истина в случае успешного завершения операции.
//
Функция ПровестиИРаспечататьЧек(Ответ, Отказ, ФормаДокумента, ПечатьПакетаДокументовВозврат = Ложь, РучнойРежимПечати = Ложь) Экспорт

    Результат = Истина;
    Ответ     = "";

    Попытка
        
        Если НачалоДня(Дата) = НачалоДня(ТекущаяДата())
         И Метаданные().ОперативноеПроведение = Метаданные.СвойстваОбъектов.ОперативноеПроведение.Разрешить Тогда
            Записать(РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Оперативный);
        Иначе
            Записать(РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Неоперативный);
        КонецЕсли;
        
        Если ПечатьПакетаДокументовВозврат Тогда
            Печать("КМ3");
        КонецЕсли;
        
    Исключение
        
        Ответ     = "Ошибка при попытке проведения документа!";
        Отказ     = Истина;
        Результат = Ложь;

        Возврат Результат;

    КонецПопытки;

    Если СтатусЧекаККМ = Перечисления.СтатусыЧековККМ.Пробитый Тогда
        Возврат Результат;
    КонецЕсли;

    Если РежимРМК
       И КассаККМ.Организация.РозничнаяТорговляОблагаетсяЕНВД
       И КассаККМ.ФормироватьНефискальныеЧеки
       И КассаККМ.РучнойРежимФормированияЧека
       И Не РучнойРежимПечати Тогда
        
        Возврат Результат;
    КонецЕсли;

    ФР = глЗначениеПеременной("мФР");
    Если ФР = Неопределено Тогда
        МассивФР      = ПолучитьСерверТО().ПолучитьСписокУстройств(
                            Перечисления.ВидыТорговогоОборудования.ФискальныйРегистратор,
                            КассаККМ);

        КоличествоФР = МассивФР.Количество();

        Если КоличествоФР = 0 Тогда
            Ответ     = ?((КассаККМ.Организация.РозничнаяТорговляОблагаетсяЕНВД И КассаККМ.ФормироватьНефискальныеЧеки),
                          ?(РежимРМК, "", "Используется нефискальный режим формирования чеков и фискальный регистратор или принтер документов не подключены.
                          |Возможно формирование только товарного чека."),
                          "Чек не пробит, т.к. не подключен фискальный регистратор!");
            Отказ     = Истина;
            Результат = Истина;
            Возврат Результат;
        ИначеЕсли КоличествоФР = 1 Тогда
            ФР = МассивФР[0];
        Иначе
            СписокФР = РаботаСТорговымОборудованием.ПолучитьСписокУстройствТОДляВыбора(МассивФР);

            ФР = СписокФР.ВыбратьЭлемент("Необходимо выбрать фискальный регистратор");
            Если ФР = Неопределено Тогда
                Ответ     = "Операция отменена пользователем.";
                Отказ     = Истина;
                Результат = Ложь;

                Если РежимРМК Тогда
                    ТекстОшибки = "Операция отменена!" + Символы.ПС +
                        "Фискальный регистратор для печати чека выбран не был!" + Символы.ПС + 
                        "Возможны расхождения данных в информационной базе и фискальном регистраторе (принтере чеков).";
                    ВывестиИнформациюОбОшибке(ТекстОшибки);
                КонецЕсли;

            Возврат Результат;
            Иначе
                ФР = ФР.Значение;
            КонецЕсли;
        КонецЕсли;
    КонецЕсли;

    ОшибкаТО = Перечисления.ТООшибкиОбщие.ПустаяСсылка();
    Если (КассаККМ.Организация.РозничнаяТорговляОблагаетсяЕНВД
       И КассаККМ.ФормироватьНефискальныеЧеки) Тогда
        ДокументЧекККМ  = Новый ТекстовыйДокумент();
        МассивСтрокЧека = Новый Массив();

        // Получение макета
        МакетЧекаККМ      = Документы.ЧекККМ.ПолучитьМакет("ЧекПокупателя");
        ОбластьШапкаЧека  = МакетЧекаККМ.ПолучитьОбласть("ШапкаЧека"  + КассаККМ.ШиринаЛенты);
        ОбластьТелоЧека   = МакетЧекаККМ.ПолучитьОбласть("ТелоЧека"   + КассаККМ.ШиринаЛенты);
        ОбластьПодвалЧека = МакетЧекаККМ.ПолучитьОбласть("ПодвалЧека" + КассаККМ.ШиринаЛенты);

        // Получение данных документа
        Запрос = Новый Запрос;
        Запрос.УстановитьПараметр("ТекущийДокумент", ЭтотОбъект.Ссылка);
        Запрос.УстановитьПараметр("Дата", Дата);

        Запрос.Текст = "
        |ВЫБРАТЬ
        |   ДокЧек.Номер,
        |   ДокЧек.Дата,
        |   ДокЧек.КассаККМ,
        |   ДокЧек.Магазин,
        |   ДокЧек.КассаККМ.Организация КАК Организация,
        |   ВЫБОР КОГДА ДокЧек.КассаККМ.Организация.ЮрФизЛицо = ЗНАЧЕНИЕ(Перечисление.ЮрФизЛицо.ЮрЛицо)
        |       ТОГДА ПРЕДСТАВЛЕНИЕ(ДокЧек.КассаККМ.Организация)
        |       ИНАЧЕ ""ИП "" +
        |           ВЫБОР   КОГДА ЕСТЬNULL(ФИОФизЛицСрезПоследнихИП.Фамилия, """") = """"
        |               ТОГДА """"
        |           ИНАЧЕ
        |               ФИОФизЛицСрезПоследнихИП.Фамилия + "" "" +
        |               ВЫБОР   КОГДА ЕСТЬNULL(ФИОФизЛицСрезПоследнихИП.Имя, """") = """"
        |                       ТОГДА """"
        |                       ИНАЧЕ ВЫРАЗИТЬ(ФИОФизЛицСрезПоследнихИП.Имя КАК СТРОКА(1)) + "". ""
        |               КОНЕЦ
        |               +
        |               ВЫБОР   КОГДА ЕСТЬNULL(ФИОФизЛицСрезПоследнихИП.Отчество, """") = """"
        |                       ТОГДА """"
        |                       ИНАЧЕ ВЫРАЗИТЬ(ФИОФизЛицСрезПоследнихИП.Отчество КАК СТРОКА(1)) + "".""
        |               КОНЕЦ
        |           КОНЕЦ
        |           + """"
        |   КОНЕЦ КАК НаименованиеОрганизации,
        |   ДокЧек.ДисконтнаяКарта,
        |   ДокЧек.СуммаДокумента,
        |   ДокЧек.ВидОперации,
        |   ДокЧек.Товары.(
        |       НомерСтроки,
        |       Номенклатура,
        |       Номенклатура.Представление КАК Товар,
        |       Номенклатура.НаименованиеПолное КАК ТоварПолноеНаименование,
        |       Номенклатура.Код КАК Код,
        |       Номенклатура.Артикул КАК Артикул,
        |       Количество,
        |       ЕдиницаИзмерения.Представление КАК ЕдиницаИзмерения,
        |       Цена,
        |       Сумма,
        |       ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры
        |   ),
        |   ДокЧек.Оплата.(
        |       НомерСтроки,
        |       ВидОплаты,
        |       Сумма
        |   ),
        |   ВЫБОР   КОГДА ЕСТЬNULL(ФИОФизЛицСрезПоследних.Фамилия, """") = """"
        |               ТОГДА """"
        |           ИНАЧЕ
        |               ФИОФизЛицСрезПоследних.Фамилия + "" "" +
        |               ВЫБОР   КОГДА ЕСТЬNULL(ФИОФизЛицСрезПоследних.Имя, """") = """"
        |                       ТОГДА """"
        |                       ИНАЧЕ ВЫРАЗИТЬ(ФИОФизЛицСрезПоследних.Имя КАК СТРОКА(1)) + "". ""
        |               КОНЕЦ
        |               +
        |               ВЫБОР   КОГДА ЕСТЬNULL(ФИОФизЛицСрезПоследних.Отчество, """") = """"
        |                       ТОГДА """"
        |                       ИНАЧЕ ВЫРАЗИТЬ(ФИОФизЛицСрезПоследних.Отчество КАК СТРОКА(1)) + "".""
        |               КОНЕЦ
        |   КОНЕЦ КАК ФИО

        |ИЗ
        |   Документ.ЧекККМ КАК ДокЧек
        |ЛЕВОЕ СОЕДИНЕНИЕ
        |   Справочник.Пользователи КАК Пользователи
        |ПО
        |   Пользователи.Ссылка = ДокЧек.Ответственный
        |ЛЕВОЕ СОЕДИНЕНИЕ
        |   Справочник.ФизическиеЛица КАК ФизическиеЛица
        |ПО
        |   Пользователи.ФизЛицо = ФизическиеЛица.Ссылка
        |ЛЕВОЕ СОЕДИНЕНИЕ
        |   РегистрСведений.ФИОФизЛиц.СрезПоследних(&Дата) КАК ФИОФизЛицСрезПоследних
        |ПО
        |   ФизическиеЛица.Ссылка = ФИОФизЛицСрезПоследних.ФизЛицо
        |ЛЕВОЕ СОЕДИНЕНИЕ
        |   РегистрСведений.ФИОФизЛиц.СрезПоследних(&Дата) КАК ФИОФизЛицСрезПоследнихИП
        |ПО
        |   ДокЧек.КассаККМ.Организация = ФИОФизЛицСрезПоследнихИП.ФизЛицо

        |ГДЕ
        |   ДокЧек.Ссылка = &ТекущийДокумент

        |УПОРЯДОЧИТЬ ПО
        |   ДокЧек.Товары.НомерСтроки,
        |   ДокЧек.Оплата.НомерСтроки
        |";

        РезультатЗапроса = Запрос.Выполнить();
        Если РезультатЗапроса.Пустой() Тогда
            Ответ     = "Пустой чек не может быть пробит на устройстве!";
            Отказ     = Истина;
            Результат = Ложь;
            Возврат Результат;
        КонецЕсли;

        Выборка = РезультатЗапроса.Выбрать();
        Выборка.Следующий();

        /////

        // Формирование чека
        // ШАПКА
        ОбластьШапкаЧека.Параметры.Заголовок = ОбщегоНазначения.СформироватьЗаголовокДокумента(Выборка,
          ?(Выборка.ВидОперации = Перечисления.ВидыОперацийЧекККМ.Возврат, "Чек (возврат)", "Чек"));

        ОбластьШапкаЧека.Параметры.Организация = Строка(Выборка.НаименованиеОрганизации);
        ОбластьШапкаЧека.Параметры.ИНН         = "ИНН: " + Выборка.Организация.ИНН;
        ДокументЧекККМ.Вывести(ОбластьШапкаЧека);


        // ТЕЛО
        ВыборкаТоваров = Выборка.Товары.Выбрать();
        Пока ВыборкаТоваров.Следующий() Цикл
            ОбластьТелоЧека.Параметры.НаименованиеТовара = ВыборкаТоваров.ТоварПолноеНаименование
                                                         + "(" + ВыборкаТоваров.ЕдиницаИзмерения + ")";
            ОбластьТелоЧека.Параметры.КоличествоЦена     = Формат(ВыборкаТоваров.Количество, "ЧЦ=17; ЧДЦ=3; ЧРД=.; ЧН=; ЧГ=0")
                                                         + " х "
                                                         + Формат(ВыборкаТоваров.Цена, "ЧЦ=15; ЧДЦ=2; ЧРД=.; ЧН=; ЧГ=0");

            КонечнаяСкидка = ВыборкаТоваров.Количество * ВыборкаТоваров.Цена - ВыборкаТоваров.Сумма;

            Если КонечнаяСкидка <> 0 Тогда
                ОбластьТелоЧека.Параметры.ЗагСкидка = ?(КонечнаяСкидка > 0, "Скидка:", "Надбавка:");
                ОбластьТелоЧека.Параметры.Скидка    = Формат(?(КонечнаяСкидка > 0, КонечнаяСкидка, -КонечнаяСкидка), "ЧЦ=15; ЧДЦ=2; ЧРД=.; ЧН=; ЧГ=0");
            КонецЕсли;

            ДокументЧекККМ.Вывести(ОбластьТелоЧека);
        КонецЦикла;
        ДокументЧекККМ.УдалитьСтроку(ДокументЧекККМ.КоличествоСтрок());

        // ПОДВАЛ
        ОбластьПодвалЧека.Параметры.Итог = Формат(Выборка.СуммаДокумента, "ЧЦ=15; ЧДЦ=2; ЧРД=.; ЧН=; ЧГ=0");

        СуммаОплат = 0;
        СуммаБезналичныхОплат = 0;
        СписокОплат = Новый Соответствие();

        ВыборкаОплат = Выборка.Оплата.Выбрать();
        Пока ВыборкаОплат.Следующий() Цикл
            Если Выборка.ВидОперации = Перечисления.ВидыОперацийЧекККМ.Возврат
               И ВыборкаОплат.ВидОплаты.ТипОплаты <> Перечисления.ТипыОплатЧекаККМ.Наличные Тогда
                СуммаБезналичныхОплат = СуммаБезналичныхОплат + ВыборкаОплат.Сумма;
            КонецЕсли;

            ЗаписьОплаты = СписокОплат.Получить(Строка(ВыборкаОплат.ВидОплаты.ТипОплаты));
            Если ЗаписьОплаты = Неопределено Тогда
                СписокОплат.Вставить(Строка(ВыборкаОплат.ВидОплаты.ТипОплаты), ВыборкаОплат.Сумма);
            Иначе
                СписокОплат.Вставить(Строка(ВыборкаОплат.ВидОплаты.ТипОплаты), ЗаписьОплаты + ВыборкаОплат.Сумма);
            КонецЕсли;
            СуммаОплат = СуммаОплат + ВыборкаОплат.Сумма;
        КонецЦикла;

        //Отдельная подготовка наличной оплаты для чека возврата
        Если Выборка.ВидОперации = Перечисления.ВидыОперацийЧекККМ.Возврат Тогда
            СписокОплат.Вставить(Строка(Перечисления.ТипыОплатЧекаККМ.Наличные), Выборка.СуммаДокумента - СуммаБезналичныхОплат);
        КонецЕсли;

        ОплатаДобавлена = Ложь;
        Для Каждого ЗнПеречисления Из Перечисления.ТипыОплатЧекаККМ Цикл
            ЗаписьОплаты = СписокОплат.Получить(Строка(ЗнПеречисления));
            Если ЗаписьОплаты <> Неопределено Тогда
                ОбластьПодвалЧека.Параметры.Оплата = ?(ОплатаДобавлена, ОбластьПодвалЧека.Параметры.Оплата + Символы.ПС, "")
                                                   + Строка(ЗнПеречисления) + ": "  + Формат(ЗаписьОплаты, "ЧЦ=15; ЧДЦ=2; ЧРД=.; ЧН=; ЧГ=0");
                ОплатаДобавлена = Истина;
            КонецЕсли;
        КонецЦикла;

        Если Выборка.ВидОперации <> Перечисления.ВидыОперацийЧекККМ.Возврат Тогда
            ОбластьПодвалЧека.Параметры.Сдача = "СДАЧА: " + Формат(СуммаОплат - Выборка.СуммаДокумента, "ЧЦ=15; ЧДЦ=2; ЧРД=.; ЧН=; ЧГ=0");
        КонецЕсли;

        ОбластьПодвалЧека.Параметры.Сотрудник = Выборка.ФИО;

        ДокументЧекККМ.Вывести(ОбластьПодвалЧека);

        Если ДокументЧекККМ.КоличествоСтрок() > 0 Тогда
            Для Индекс = 1 По ДокументЧекККМ.КоличествоСтрок() Цикл
                МассивСтрокЧека.Добавить(ДокументЧекККМ.ПолучитьСтроку(Индекс));
            КонецЦикла;

            // Открыть нефискальный чек
            ОшибкаТО = ПолучитьСерверТО().ОткрытьЧек(ФР, "",
                                                     ВидОперации = Перечисления.ВидыОперацийЧекККМ.Возврат,
                                                     НомерЧекаККМ, НомерСменыККМ, Ложь);

            Если Не ЗначениеЗаполнено(ОшибкаТО) Тогда
                // Напечатать строки полученного из макета чека
                ОшибкаТО = ПолучитьСерверТО().ПечатьТекста(ФР, МассивСтрокЧека, КассаККМ.ШиринаЛенты);

                // Закрыть чек
                ОшибкаТО = ПолучитьСерверТО().ЗакрытьЧек(ФР, 0, 0);
            КонецЕсли;
        КонецЕсли;
    Иначе
        Запрос = Новый Запрос(
        "ВЫБРАТЬ
        |   ТчТовары.Номенклатура.Представление КАК Номенклатура,
        |   ТчТовары.ХарактеристикаНоменклатуры.Представление КАК ХарактеристикаНоменклатуры,
        |   ТчТовары.ЕдиницаИзмерения.Представление КАК ЕдиницаИзмерения,
        |   ТчТовары.Цена КАК Цена,
        |   ТчТовары.Количество КАК Количество,
        |   ВЫБОР
        |       КОГДА ТчТовары.Цена * ТчТовары.Количество = 0
        |           ТОГДА 0
        |       ИНАЧЕ (1 - ТчТовары.Сумма / (ТчТовары.Цена * ТчТовары.Количество)) * 100
        |   КОНЕЦ КАК ПроцентСкидкиНаценки,
        |   ТчТовары.СтавкаНДС,
        |   ТчТовары.СуммаНДС
        |ИЗ
        |   Документ.ЧекККМ.Товары КАК ТчТовары
        |ГДЕ
        |   ТчТовары.Ссылка = &Ссылка");
        Запрос.УстановитьПараметр("Ссылка", Ссылка);
        РезультатЗапроса = Запрос.Выполнить();
        Если РезультатЗапроса.Пустой() Тогда
            Ответ     = "Пустой чек не может быть пробит на фискальном регистраторе!";
            Отказ     = Истина;
            Результат = Ложь;
            
            Если РежимРМК Тогда
                ТекстОшибки = "Пустой чек!" + Символы.ПС +
                    "Пустой чек не может быть распечатан на фискальном регистраторе!" + Символы.ПС + 
                    "Это не критичная ошибка, т.к. проведенный пустой чек не влияет на данные информационной базы.";
                ВывестиИнформациюОбОшибке(ТекстОшибки);
            КонецЕсли;
            
            Возврат Результат;
        КонецЕсли;


        Выборка = РезультатЗапроса.Выбрать();
        ТаблицаТоваров = Новый ТаблицаЗначений;
        ТаблицаТоваров.Колонки.Добавить("Наименование");
        ТаблицаТоваров.Колонки.Добавить("НомерСекции");
        ТаблицаТоваров.Колонки.Добавить("Цена");
        ТаблицаТоваров.Колонки.Добавить("Количество");
        ТаблицаТоваров.Колонки.Добавить("Скидка");
        ТаблицаТоваров.Колонки.Добавить("СтавкаНДС");

        ПечататьНДСВКассовыхЧекахИзДокументовЧекККМ = УправлениеПользователями.ПолучитьЗначениеПоУмолчанию(глЗначениеПеременной("глТекущийПользователь"), "ПечататьНДСВКассовыхЧекахИзДокументовЧекККМ");

        Пока Выборка.Следующий() Цикл
            Товар = ТаблицаТоваров.Добавить();

            Товар.Наименование = СокрЛП(Выборка.Номенклатура)
                               + "(" + СокрЛП(Выборка.ЕдиницаИзмерения)
                               + ?(ПустаяСтрока(Выборка.ХарактеристикаНоменклатуры), "", ", " + СокрЛП(Выборка.ХарактеристикаНоменклатуры)) + ")";
            
            Товар.НомерСекции  = 1;
            Товар.Цена         = Выборка.Цена;
            Товар.Количество   = Выборка.Количество;
            Товар.Скидка       = Выборка.ПроцентСкидкиНаценки;
            Товар.СтавкаНДС    = ?(ПечататьНДСВКассовыхЧекахИзДокументовЧекККМ, Ценообразование.ПолучитьСтавкуНДС(Выборка.СтавкаНДС), 0);
        КонецЦикла;

        ОшибкаТО = ПечатьЧекаККМ(ФР, НомерЧекаККМ, НомерСменыККМ,
                                 ТаблицаТоваров, ПолучитьСуммуНаличнойОплаты(),
                                 ПолучитьСуммуБезналичнойОплаты() + ПолучитьСуммуОплатыПодарочнымиСертификатами(),
                                 ВидОперации = Перечисления.ВидыОперацийЧекККМ.Возврат);
    КонецЕсли;

    Если НЕ ЗначениеЗаполнено(ОшибкаТО) Тогда
        СтатусЧекаККМ = Перечисления.СтатусыЧековККМ.Пробитый;
        Попытка
            Записать(РежимЗаписиДокумента.Запись);
        Исключение

            Ответ     = "Не удалось записать документ с установленными параметрами пробитого чека.";
            Отказ     = Истина;
            Результат = Ложь;
            
            Если РежимРМК Тогда
                ТекстОшибки = "Ошибка записи чека!" + Символы.ПС +
                    "Не удалось установить признак пробития чека!" + Символы.ПС + 
                    "Это не критичная ошибка, т.к. при закрытии смены чек в любом случае попадет в отчет о продажах.";
                ВывестиИнформациюОбОшибке(ТекстОшибки);
            КонецЕсли;
        КонецПопытки;
    Иначе

        Ответ     = ПолучитьСерверТО().ПолучитьТекстОшибкиФРТО(ОшибкаТО);
        Отказ     = Истина;
        Результат = Ложь;
        
        Если РежимРМК Тогда
            ТекстОшибки = "Ошибка фискального регистратора!" + Символы.ПС +
                Ответ + Символы.ПС + "!" +
                "Необходимо проверить настройки подключения фискального регистратора.";
            ВывестиИнформациюОбОшибке(ТекстОшибки);
        КонецЕсли;

    КонецЕсли;

    Если ПараметрыСеанса.НаличиеОбменаДаннымиПоКассе И Не ПараметрыСеанса.ЭтоГлавныйУзелОбменаПоКассе Тогда
        
        //определим настройку для выполнения
        СтруктураНастроекОбмена = ПроцедурыОбменаДаннымиПоКассе.ПолучитьСтруктуруНастроекОбменаВУзлеКассы();
        
        Если Не ЗначениеЗаполнено(СтруктураНастроекОбмена.НастройкаОбменаДанными) Тогда
            
            Сообщить("Не смог определить настройку обмена данными для узла кассы!
                     |Необходимо в форме узла обмена выбрать соответствующую настройку обмена!", СтатусСообщения.ОченьВажное);
            
        Иначе
            
            ПроцедурыОбменаДанными.ВыполнитьОбменДаннымиПоПроизвольнойНастройке(СтруктураНастроекОбмена.НастройкаОбменаДанными, Ложь, глЗначениеПеременной("глОбработкаАвтоОбменДанными"));
            
        КонецЕсли;
        
    КонецЕсли;
    
    Возврат Результат;

КонецФункции // ПровестиИРаспечататьЧек()

// Функция осуществляет операцию оплаты картой, используя подключенную эквайринговую систему.
//
// Параметры:
//  СуммаОплаты - сумма оплаты
//
Функция ОплатитьКартой(СуммаОплаты) Экспорт

    Перем ЭС;
    Перем ФР;
    
    РезультатФункции = Истина;
    
    Если РаботаСТорговымОборудованием.ПолучитьПроверитьПараметрыДляОплатыКартой(ЭС, ФР) Тогда
        КодRRN = Неопределено;

        Если ВидОперации = Перечисления.ВидыОперацийЧекККМ.Продажа Тогда
            Результат = ПолучитьСерверТО().ОплатитьПлатежнойКартой(ЭС, СуммаОплаты, КодRRN, ФР);
        Иначе
            Результат = ПолучитьСерверТО().ОтменитьПлатежПоПлатежнойКарте(ЭС, СуммаОплаты, КодRRN, ФР);
        КонецЕсли;
        
        Если ЗначениеЗаполнено(Результат) Тогда
            
            Ошибка = ПолучитьСерверТО().ПолучитьТекстОшибкиТО(Результат);
            Предупреждение(Ошибка);
            
            РезультатФункции = Ложь;
            
        КонецЕсли;
    КонецЕсли;

    Возврат РезультатФункции;
    
КонецФункции // ОплатитьКартой()

// Выводит в окне информацию об ошибке
// 
Процедура ВывестиИнформациюОбОшибке(ТекстОшибки) Экспорт

    ФормаИнформацииОбОшибке = ПолучитьФорму("ФормаИнформацииОбОшибке");
    ФормаИнформацииОбОшибке.ТекстОшибки = ТекстОшибки;
    ФормаИнформацииОбОшибке.ОткрытьМодально();

КонецПроцедуры

// Вывести подготовленные сообщения
//
// Параметры
//  ТаблицаСообщений - Подготовленная таблица сообщений
//
Процедура ВывестиСообщенияКассиру(ТаблицаСообщений) Экспорт

    Если НЕ ЗначениеЗаполнено(ТаблицаСообщений)  Тогда
        Возврат;
    ИначеЕсли ТаблицаСообщений.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;
    
    Для каждого СтрокаТаблицыСообщений Из ТаблицаСообщений Цикл
        ВывестиИнформациюОбОшибке(СтрокаТаблицыСообщений.ТекстСообщения);
    КонецЦикла;
    

КонецПроцедуры // ВывестиСообщенияКассиру()


// Определяет скидки после закрытия чека.
//
// Параметры:
//  Нет
//
Процедура ОпределитьСообщенияКассируПослеОформленияЧека() Экспорт
    
    Если ВидОперации = Перечисления.ВидыОперацийЧекККМ.Возврат Тогда
        Возврат;
    КонецЕсли;
    
    мСуммаДокументаБезСкидок = Ценообразование.ПолучитьСуммуДокументаБезСкидки(Товары);
    
        
    СтруктураПараметров = Новый Структура;
    СтруктураПараметров.Вставить("СуммаДокумента"   , мСуммаДокументаБезСкидок);
    СтруктураПараметров.Вставить("Получатель"       , ВладелецДисконтнойКарты);
    СтруктураПараметров.Вставить("Карта"            , ДисконтнаяКарта);
    СтруктураПараметров.Вставить("ВидыОплат"        , МассивОплатДляСкидок());
    СтруктураПараметров.Вставить("УчитыватьНДС"     , Истина);
    СтруктураПараметров.Вставить("СуммаВключаетНДС" , Истина);
    СтруктураПараметров.Вставить("НомерЧека"        , НомерЧекаККМ);
    СтруктураПараметров.Вставить("Купоны"           , Купоны.ВыгрузитьКолонку("СкидкаНаценка"));
    
    СтруктураПараметров.Вставить("МоментПроверкиСообщений", Перечисления.ТочкиВыдачиСообщенияКассиру.ПослеОформленияЧека);
    СтруктураПараметров.Вставить("ТолькоСообщения"        , Истина);
    
    ТаблицаСообщений = Новый ТаблицаЗначений;
    
    УправлениеМаркетинговымиАкциями.РассчитатьСообщенияПриПродаже(ЭтотОбъект, Товары, Скидки, Подарки, СтруктураПараметров, ТаблицаСообщений);
    
    ВывестиСообщенияКассиру(ТаблицаСообщений);
    
КонецПроцедуры // ОпределитьСообщенияКассируПослеОформленияЧека()


#КонецЕсли

// Возвращает доступные варианты печати документа.
//
// Вовращаемое значение:
//  Структура, каждая строка которой соответствует одному из вариантов печати.
//
Функция ПолучитьСтруктуруПечатныхФорм() Экспорт

    СтруктураМакетов = Новый Структура("Чек", "Товарный чек");
    Если КассаККМ.Организация.РозничнаяТорговляОблагаетсяЕНВД
       И КассаККМ.ФормироватьНефискальныеЧеки Тогда
        СтруктураМакетов.Вставить( "ТоварныйЧекДляПД",    "Товарный чек для принтера документов");
    КонецЕсли;
    СтруктураМакетов.Вставить( "КМ3",    "Пакет документов на возврат");
    Возврат СтруктураМакетов;

КонецФункции // ПолучитьСтруктуруПечатныхФорм()

// Функция считает сумму, оплаченную наличными.
//
// Возвращаемое значение:
//  Число - сумма, оплаченная наличными.
//
Функция ПолучитьСуммуНаличнойОплаты() Экспорт

    СуммаНаличнойОплаты = 0;
    Для Каждого ТекОплата Из Оплата Цикл
        Если ЗначениеЗаполнено(ТекОплата.ВидОплаты) И ТекОплата.ВидОплаты.ТипОплаты = Перечисления.ТипыОплатЧекаККМ.Наличные Тогда
            СуммаНаличнойОплаты = СуммаНаличнойОплаты + ТекОплата.Сумма;
        КонецЕсли;
    КонецЦикла;

    Возврат СуммаНаличнойОплаты;

КонецФункции // ПолучитьСуммуНаличнойОплаты()

// Функция считает сумму, оплаченную безналичными.
//
// Возвращаемое значение:
//  Число - сумма, оплаченная безналично.
//
Функция ПолучитьСуммуБезналичнойОплаты() Экспорт

    СуммаБезналичнойОплаты = 0;
    Для Каждого ТекОплата Из Оплата Цикл
        Если ЗначениеЗаполнено(ТекОплата.ВидОплаты) И ТекОплата.ВидОплаты.ТипОплаты <> Перечисления.ТипыОплатЧекаККМ.Наличные 
        И НЕ ТекОплата.ВидОплаты = Справочники.ВидыОплатЧекаККМ.ОплатаПодарочнымСертификатом Тогда
            СуммаБезналичнойОплаты = СуммаБезналичнойОплаты + ТекОплата.Сумма;
        КонецЕсли;
    КонецЦикла;

    Возврат СуммаБезналичнойОплаты;

КонецФункции // ПолучитьСуммуБезналичнойОплаты()

// Функция считает сумму, оплаченную подарочными сертификатами.
//
// Возвращаемое значение:
//  Число - сумма, оплаченная подарочными сертификатами.
//
Функция ПолучитьСуммуОплатыПодарочнымиСертификатами() Экспорт

    СуммаОплаты = 0;
    Для Каждого ТекОплата Из Оплата Цикл
        Если ТекОплата.ВидОплаты = Справочники.ВидыОплатЧекаККМ.ОплатаПодарочнымСертификатом Тогда
            СуммаОплаты = СуммаОплаты + ТекОплата.Сумма;
        КонецЕсли;
    КонецЦикла;

    Возврат СуммаОплаты;

КонецФункции // ПолучитьСуммуБезналичнойОплаты()


// Функция считает сумму, оплаченную безналичными по платежным картам.
//
// Возвращаемое значение:
//  Число - сумма, оплаченная наличными.
//
Функция ПолучитьСуммуОплатыПлатежнымиКартами() Экспорт

    СуммаОплаты = 0;
    Для Каждого ТекОплата Из Оплата Цикл
        Если ЗначениеЗаполнено(ТекОплата.ВидОплаты) И ТекОплата.ВидОплаты.ТипОплаты = Перечисления.ТипыОплатЧекаККМ.ПлатежнаяКарта Тогда
            СуммаОплаты = СуммаОплаты + ТекОплата.Сумма;
        КонецЕсли;
    КонецЦикла;

    Возврат СуммаОплаты;

КонецФункции // ПолучитьСуммуОплатыПлатежнымиКартами()

// Функция считает сумму, оплаченную безналичными по банковскому кредиту.
//
// Возвращаемое значение:
//  Число - сумма, оплаченная наличными.
//
Функция ПолучитьСуммуОплатыБанковскимКредитом() Экспорт

    СуммаОплаты = 0;
    Для Каждого ТекОплата Из Оплата Цикл
        Если ЗначениеЗаполнено(ТекОплата.ВидОплаты) И ТекОплата.ВидОплаты.ТипОплаты = Перечисления.ТипыОплатЧекаККМ.БанковскийКредит Тогда
            СуммаОплаты = СуммаОплаты + ТекОплата.Сумма;
        КонецЕсли;
    КонецЦикла;

    Возврат СуммаОплаты;

КонецФункции // ПолучитьСуммуОплатыПлатежнымиКартами()

// удаляет скидки лишние при возврате
//
// Параметры:
//  Нет
//
Процедура УдалитьНенужныеСкидкиПриВозврате() Экспорт

    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
    |   Товары.КлючСтроки
    |ПОМЕСТИТЬ ДокТовары
    |ИЗ
    |   &Товары КАК Товары
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |   Скидки.КлючСтроки,
    |   Скидки.НомерСтроки
    |ПОМЕСТИТЬ ДокСкидки
    |ИЗ
    |   &Скидки КАК Скидки
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |   ДокСкидки.КлючСтроки,
    |   ДокСкидки.НомерСтроки
    |ИЗ
    |   ДокСкидки КАК ДокСкидки
    |       ЛЕВОЕ СОЕДИНЕНИЕ ДокТовары КАК ДокТовары
    |       ПО ДокСкидки.КлючСтроки = ДокТовары.КлючСтроки
    |ГДЕ
    |   ДокТовары.КлючСтроки ЕСТЬ NULL ";
    
    Запрос.УстановитьПараметр("Товары", Товары);
    Запрос.УстановитьПараметр("Скидки", Скидки);
    
    Результат = Запрос.Выполнить();
    Выборка = Результат.Выбрать();
    
    МассивУдаляемыхСтрок = Новый Массив;
    
    Пока Выборка.Следующий() Цикл
        СтрокаПодарки = Скидки[Выборка.НомерСтроки - 1];
        МассивУдаляемыхСтрок.Добавить(СтрокаПодарки);
    КонецЦикла;
    
    Для каждого СтрокаПодарки Из МассивУдаляемыхСтрок Цикл
        Скидки.Удалить(СтрокаПодарки);
    КонецЦикла;

КонецПроцедуры // УдалитьНенужныеСкидкиПриВозврате()

// Пересчитывает скидки в документе возврата при изменении количества
//
// Параметры
//  СтрокаТабличнойЧасти - строка табличной части товары в которой изменено количество
//
Процедура ПересчитатьСкидкиВозврата(СтрокаТабличнойЧасти) Экспорт
    
    КлючСтроки = СтрокаТабличнойЧасти.КлючСтроки;
    Запрос = Новый Запрос;
    Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |   ЧекККМТовары.Количество * ВЫБОР
    |       КОГДА ЧекККМТовары.Коэффициент = 0
    |           ТОГДА 1
    |       ИНАЧЕ ЧекККМТовары.Коэффициент
    |   КОНЕЦ / &КоличествоВЗапрос КАК КоэффициентПересчета
    |ИЗ
    |   Документ.ЧекККМ.Товары КАК ЧекККМТовары
    |ГДЕ
    |   ЧекККМТовары.КлючСтроки = &КлючСтроки
    |   И ЧекККМТовары.Ссылка = &Ссылка";
    
    Запрос.УстановитьПараметр("КлючСтроки", КлючСтроки);
    Запрос.УстановитьПараметр("Ссылка", ЧекККМПродажа);
    
    КоличествоВЗапрос = ?(СтрокаТабличнойЧасти.Коэффициент = 0 ,1, СтрокаТабличнойЧасти.Коэффициент)*?(СтрокаТабличнойЧасти.Количество = 0, 1, СтрокаТабличнойЧасти.Количество);
    Запрос.УстановитьПараметр("КоличествоВЗапрос", КоличествоВЗапрос);
    
    Результат = Запрос.Выполнить();
    Выборка = Результат.Выбрать();
    
    Если Выборка.Следующий() Тогда
    
        КоэффициентПересчета = Выборка.КоэффициентПересчета;
        Если НЕ КоэффициентПересчета = 0 Тогда
            СтруктураПоиска = Новый Структура;
            СтруктураПоиска.Вставить("КлючСтроки", КлючСтроки);
            СтрокиЧекККМПродажи = ЧекККМПродажа.Скидки.НайтиСтроки(СтруктураПоиска);
            Для каждого СтрокаЧекККМПродажи Из СтрокиЧекККМПродажи Цикл
                
                СтруктураПоиска.Вставить("СкидкаНаценка", СтрокаЧекККМПродажи.СкидкаНаценка);
                СтрокиСкидки = Скидки.НайтиСтроки(СтруктураПоиска);
                Для каждого СтрокаСкидки Из СтрокиСкидки Цикл
                    
                    СтрокаСкидки.Сумма = СтрокаЧекККМПродажи.Сумма / КоэффициентПересчета;
                    
                КонецЦикла;
            КонецЦикла;
        КонецЕсли;
    КонецЕсли;
    
    
КонецПроцедуры // ПересчитатьСкидкиВозврата()

// Получает сумму номиналов подарочных сертификатов
//
//
// Возвращаемое значение:
//   Число
//
Функция ПолучитьСуммуНоминаловПодарочныхСертификатов() Экспорт
    СуммаПогашения = 0;
    Если ПогашениеПодарочныхСертификатов.Количество() >0 Тогда
    
        Запрос = Новый Запрос;
        Запрос.Текст = "ВЫБРАТЬ
        |   ВЫРАЗИТЬ(ПогашениеПодарочныхСертификатов.ПодарочныйСертификат КАК Справочник.Номенклатура) КАК Номенклатура
        |ПОМЕСТИТЬ ТабПогашения
        |ИЗ
        |   &ПогашениеПодарочныхСертификатов КАК ПогашениеПодарочныхСертификатов
        |;
        |
        |////////////////////////////////////////////////////////////////////////////////
        |ВЫБРАТЬ
        |   СУММА(ТабПогашения.Номенклатура.Номинал) КАК СуммаПогашения
        |ИЗ
        |   ТабПогашения КАК ТабПогашения";
        
        Запрос.УстановитьПараметр("ПогашениеПодарочныхСертификатов", ПогашениеПодарочныхСертификатов.Выгрузить());
        
        Результат = Запрос.Выполнить();
        Выборка = Результат.Выбрать();
        
        Если Выборка.Следующий() Тогда
            Возврат Выборка.СуммаПогашения;
        Иначе
            Возврат 0;
        КонецЕсли;
    Иначе
        Возврат 0;
    КонецЕсли;
КонецФункции // ПолучитьСуммуНоминаловПодарочныхСертификатов()

// Получить сумму погашения подарочными сертификатами
//
// Параметры
//
// Возвращаемое значение:
//   Число
//
Функция ПолучитьСуммуПогашенияПодарочнымиСертификатами() Экспорт

    Возврат МИН(ПолучитьСуммуНоминаловПодарочныхСертификатов(), Товары.Итог("Сумма"));
    
КонецФункции // ПолучитьСуммуПогашенияПодарочнымиСертификатами()

// Добавляет или корректирует оплату подарочным сертификатом при необходимости
//
// Параметры
//  Нет
//
Процедура ДобавитьОплатуПодарочнымСертификатом() Экспорт

    СуммаПогашения = ПолучитьСуммуПогашенияПодарочнымиСертификатами();
    
    СтрокаОплаты = Оплата.Найти(Справочники.ВидыОплатЧекаККМ.ОплатаПодарочнымСертификатом);
    
    Если СуммаПогашения > 0 Тогда
        
        Если СтрокаОплаты = Неопределено Тогда
            СтрокаОплаты = Оплата.Добавить();
            СтрокаОплаты.ВидОплаты = Справочники.ВидыОплатЧекаККМ.ОплатаПодарочнымСертификатом;
        КонецЕсли;
        СтрокаОплаты.Сумма = СуммаПогашения;
    ИначеЕсли Не СтрокаОплаты = Неопределено И (Товары.Итог("Сумма") > 0) Тогда
        Оплата.Удалить(СтрокаОплаты);
        ПогашениеПодарочныхСертификатов.Очистить();
    КонецЕсли; 
    
КонецПроцедуры // ДобавитьОплатуПодарочнымСертификатом()


// Возвращает массив оплат без купонов и скидок
//
// Возвращаемое значение:
//  Массив
//
Функция МассивОплатДляСкидок() Экспорт

    МассивОплат = Новый Массив;
    МассивОплат = Оплата.ВыгрузитьКолонку("ВидОплаты");
    
    Если МассивОплат.Количество()=0 Тогда
        МассивОплат.Добавить(Справочники.ВидыОплатЧекаККМ.Наличные);
    КонецЕсли;
    
    Возврат МассивОплат;

КонецФункции // МассивОплатДляСкидок()

// Округляет сумму чека по правилам установленным в магазине
//
// Параметры 
//  Нет
//
Процедура ОкруглитьСуммуЧека() Экспорт
    
    ПорядокОкругленияСуммыЧекаВПользуПокупателя = КассаККМ.Магазин.ПорядокОкругленияСуммыЧекаВПользуПокупателя;
    
    Если Не ЗначениеЗаполнено(ПорядокОкругленияСуммыЧекаВПользуПокупателя) ИЛИ ПорядокОкругленияСуммыЧекаВПользуПокупателя = Перечисления.ПорядкиОкругления.Окр0_01 ИЛИ Товары.Количество()= 0 Тогда
        Возврат;
    КонецЕсли;
    
    ЗначениеОкругления = Число(Строка(ПорядокОкругленияСуммыЧекаВПользуПокупателя));
    
    Если ЗначениеЗаполнено(ЗначениеОкругления) Тогда
        СуммаБезОкругления = Товары.Итог("Сумма");
        ОкругленнаяСумма = Цел(СуммаБезОкругления / ЗначениеОкругления) * ЗначениеОкругления;
        Округление = СуммаБезОкругления - ОкругленнаяСумма;
        Если Округление > 0 Тогда
            Запрос = Новый Запрос;
            Запрос.Текст = "ВЫБРАТЬ
            |   Товары.НомерСтроки,
            |   ВЫРАЗИТЬ(Товары.Номенклатура КАК Справочник.Номенклатура) КАК Номенклатура,
            |   Товары.Сумма КАК Сумма
            |ПОМЕСТИТЬ ТаблицаВЗапросе
            |ИЗ
            |   &Товары КАК Товары
            |
            |ИНДЕКСИРОВАТЬ ПО
            |   Сумма
            |;
            |
            |////////////////////////////////////////////////////////////////////////////////
            |ВЫБРАТЬ
            |   ТаблицаВЗапросе.НомерСтроки,
            |   ТаблицаВЗапросе.Номенклатура,
            |   ТаблицаВЗапросе.Сумма КАК Сумма
            |ИЗ
            |   ТаблицаВЗапросе КАК ТаблицаВЗапросе
            |ГДЕ
            |   НЕ ТаблицаВЗапросе.Номенклатура.ПодарочныйСертификат
            |
            |УПОРЯДОЧИТЬ ПО
            |   Сумма УБЫВ";
            
            Запрос.УстановитьПараметр("Товары", Товары);
            
            Результат = Запрос.Выполнить();
            Выборка = Результат.Выбрать();
            
            Если Выборка.Следующий() Тогда
                СтрокаМаксимальнойСуммы = Товары[Выборка.НомерСтроки - 1]
            Иначе
                Возврат;
            КонецЕсли;
            
            Если ЗначениеОкругления >= СтрокаМаксимальнойСуммы.Сумма Тогда
                Возврат;
            КонецЕсли;
            
            СтрокаМаксимальнойСуммы.Сумма = СтрокаМаксимальнойСуммы.Сумма - Округление;
            
            СтрокаМаксимальнойСуммы.СуммаНДС  = Ценообразование.РассчитатьСуммуНДС(СтрокаМаксимальнойСуммы.Сумма, 
                                                                                   Истина,
                                                                                   Истина,
                                                                                   Ценообразование.ПолучитьСтавкуНДС(СтрокаМаксимальнойСуммы.СтавкаНДС));
            
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры // ОкруглитьСуммуЧека()


// <Описание функции>
//
// Параметры:
//  СтрокаТабличнойЧасти - ссылка на строку табличной части
//
// Возвращаемое значение:
//   Число - цена возврата
//
Функция НайтиЦенуВозврата(СтрокаТабличнойЧасти) Экспорт

    Запрос = Новый Запрос;
    Запрос.Текст = 
    "ВЫБРАТЬ
    |   ВЫБОР
    |       КОГДА ВложенныйЗапрос.Количество = 0
    |               ИЛИ &Коэффициент = 0
    |           ТОГДА 0
    |       ИНАЧЕ ВложенныйЗапрос.Сумма / ВложенныйЗапрос.Количество / &Коэффициент
    |   КОНЕЦ КАК Цена
    |ИЗ
    |   (ВЫБРАТЬ
    |       СУММА(ЧекККМТовары.Сумма) КАК Сумма,
    |       СУММА(ВЫБОР
    |               КОГДА ЕСТЬNULL(ЧекККМТовары.Номенклатура.ЕдиницаХраненияОстатков.Коэффициент, 1) = 0
    |                   ТОГДА 0
    |               ИНАЧЕ ЧекККМТовары.Количество * ВЫБОР
    |                       КОГДА ЧекККМТовары.Коэффициент = 0
    |                           ТОГДА 1
    |                       ИНАЧЕ ЧекККМТовары.Коэффициент
    |                   КОНЕЦ / ЕСТЬNULL(ЧекККМТовары.Номенклатура.ЕдиницаХраненияОстатков.Коэффициент, 1)
    |           КОНЕЦ) КАК Количество
    |   ИЗ
    |       Документ.ЧекККМ.Товары КАК ЧекККМТовары
    |   ГДЕ
    |       ЧекККМТовары.Ссылка = &Ссылка
    |       И ЧекККМТовары.ХарактеристикаНоменклатуры = &ХарактеристикаНоменклатуры
    |       И ЧекККМТовары.Номенклатура = &Номенклатура
    |       И ЧекККМТовары.ПроцентСкидкиНаценки = &ПроцентСкидкиНаценки) КАК ВложенныйЗапрос";
    
    Запрос.УстановитьПараметр("Ссылка"                    , ЧекККМПродажа);
    КоэффициентВЗапрос = ?(СтрокаТабличнойЧасти.Коэффициент  = 0, 1, СтрокаТабличнойЧасти.Коэффициент);
    Запрос.УстановитьПараметр("Коэффициент"               , КоэффициентВЗапрос);
    Запрос.УстановитьПараметр("Номенклатура"              , СтрокаТабличнойЧасти.Номенклатура);
    Запрос.УстановитьПараметр("ХарактеристикаНоменклатуры", СтрокаТабличнойЧасти.ХарактеристикаНоменклатуры);
    Запрос.УстановитьПараметр("ПроцентСкидкиНаценки"      , СтрокаТабличнойЧасти.ПроцентСкидкиНаценки);
    
    Результат = Запрос.Выполнить();
    Выборка = Результат.Выбрать();
    
    Если Выборка.Следующий() Тогда
        Возврат Выборка.Цена;
    Иначе
        Возврат 0;
    КонецЕсли;
    

КонецФункции // НайтиЦенуВозврата()

/////////////////////////////////////////////////////////////////////////////////
// ПРОЦЕДУРЫ И ФУНКЦИИ ДЛЯ ОБЕСПЕЧЕНИЯ ПРОВЕДЕНИЯ ДОКУМЕНТА

// Проверяет правильность заполнения шапки документа.
//
// Параметры:
//  СтруктураШапкиДокумента - выборка из результата запроса по шапке документа.
//  Отказ                   - флаг отказа в проведении.
//  Заголовок               - заголовок сообщения об ошибках.
//
Процедура ПроверитьЗаполнениеШапки(СтруктураШапкиДокумента, Отказ, Заголовок)

    // Укажем, что надо проверить.
    СтруктураОбязательныхПолей = Новый Структура("КассаККМ" + ?(ВидОперации = Перечисления.ВидыОперацийЧекККМ.Возврат, ", ЧекККМПродажа, ХозяйственнаяОперация", ""));

    
    
    // Теперь вызовем общую процедуру проверки.
    ТестированиеОбъектов.ПроверитьЗаполнениеШапкиДокумента(ЭтотОбъект, СтруктураОбязательныхПолей, Отказ, Заголовок);

    Если СтатусЧекаККМ = Перечисления.СтатусыЧековККМ.Аннулированный Тогда
        СтрокаСообщения = "Нельзя проводить аннулированный чек";
        ОбщегоНазначения.ОшибкаПриПроведении(СтрокаСообщения, Отказ, Заголовок);
    КонецЕсли;
КонецПроцедуры // ПроверитьЗаполнениеШапки()

// Проверяет правильность заполнения строк табличной части "Товары".
//
// Параметры:
//  ТаблицаПоТоварам        - таблица значений, содержащая данные для проведения и проверки ТЧ Товары.
//  СтруктураШапкиДокумента - выборка из результата запроса по шапке документа.
//  Отказ                   - флаг отказа в проведении.
//  Заголовок               - заголовок сообщения об ошибках.
//
Процедура ПроверитьЗаполнениеТабличнойЧастиТовары(ТаблицаПоТоварам, СтруктураШапкиДокумента, Отказ, Заголовок, Результат)

    ИмяТабличнойЧасти = "Товары";

    // Укажем, что надо проверить:
    СтруктураОбязательныхПолей = Новый Структура("Номенклатура, ХарактеристикаНоменклатуры, Количество, Склад");
    
    // Теперь позовем общую процедуру проверки.
    ОбработкаТабличныхЧастей.ПроверитьЗаполнениеТабличнойЧасти(ЭтотОбъект, "Товары", СтруктураОбязательныхПолей, Отказ, Заголовок);
    
    Если Не ВидОперации = Перечисления.ВидыОперацийЧекККМ.Возврат Тогда
        // Корректирует состав "нулевых" полей
        УправлениеЗапасами.ПроверитьЗаполнениеТабличнойЧастиПоТипамСкладов(ЭтотОбъект, "Товары", Отказ, Заголовок, Результат);
        
        Если НЕ СтруктураОбязательныхПолей.Свойство("Цена") Тогда
            УправлениеЗапасами.ПроверитьЦеныСертификатов(ЭтотОбъект, "Товары", Отказ, Заголовок);
        КонецЕсли;
    Иначе
        // Здесь подарочных сертификатов быть не должно.
        УправлениеЗапасами.ПроверитьЧтоНетПодарочныхСертификатов(ЭтотОбъект, "Товары", ТаблицаПоТоварам, Отказ, Заголовок);
    КонецЕсли;
    
    // Проверим заполнение полей "Единица измерения" и "Коэффициент" для позиций номенклатуры, не являющихся услугами
    ОбработкаТабличныхЧастей.ПроверитьЗаполнениеПолейЕдиницаИзмеренияИКоэффициентДляТабличнойЧасти(ЭтотОбъект, "Товары", Отказ, Заголовок);
    
КонецПроцедуры // ПроверитьЗаполнениеТабличнойЧастиТовары()

// Проверяет правильность заполнения строк табличной части "СоставНабора".
//
// Параметры: 
//  ТаблицаПоКомплектам     - таблица значений, содержащая данные для проведения и проверки ТЧ СоставНабора,
//  СтруктураШапкиДокумента - выборка из результата запроса по шапке документа,
//  Отказ                   - флаг отказа в проведении,
//  Заголовок               - строка, заголовок сообщения об ошибке проведения.
//
Процедура ПроверитьЗаполнениеТабличнойЧастиСоставНабора(ТаблицаПоКомплектам, СтруктураШапкиДокумента, Отказ, Заголовок, Результат)

    // Проверить заполнение ТЧ "Состав набора".
    СтруктураОбязательныхПолей = Новый Структура("Номенклатура, ХарактеристикаНоменклатуры, Количество, Склад, Цена");
    
    // Теперь позовем общую процедуру проверки.
    ОбработкаТабличныхЧастей.ПроверитьЗаполнениеТабличнойЧасти(ЭтотОбъект, "СоставНабора", СтруктураОбязательныхПолей, Отказ, Заголовок);
    
    Если Не ВидОперации = Перечисления.ВидыОперацийЧекККМ.Возврат Тогда
        // Корректирует состав "нулевых" полей
        УправлениеЗапасами.ПроверитьЗаполнениеТабличнойЧастиПоТипамСкладов(ЭтотОбъект, "СоставНабора", Отказ, Заголовок, Результат);
    КонецЕсли;
    
    // Здесь услуг быть не должно.
    УправлениеЗапасами.ПроверитьЧтоНетУслуг(ЭтотОбъект, "СоставНабора", ТаблицаПоКомплектам, Отказ, Заголовок);
    
    // Здесь комплектов быть не должно.
    УправлениеЗапасами.ПроверитьЧтоНетКомплектов(ЭтотОбъект, "СоставНабора", ТаблицаПоКомплектам, Отказ, Заголовок);
    
    // Здесь подарочных сертификатов быть не должно.
    УправлениеЗапасами.ПроверитьЧтоНетПодарочныхСертификатов(ЭтотОбъект, "СоставНабора", ТаблицаПоКомплектам, Отказ, Заголовок);
КонецПроцедуры // ПроверитьЗаполнениеТабличнойЧастиТовары()


// Получает развернутые строки расхождения по товарам при возврате
// 
Функция ПолучитьСтрокиРасхожденияПоТоварамСЧекомПродажи(ТаблицаПоТоварам, ДанныеДокумента, РазрезАналитики = "Склад") Экспорт
    
    СтрокиРасхождения = Новый ТаблицаЗначений;
    Если ДанныеДокумента.ВидОперации <> Перечисления.ВидыОперацийЧекККМ.Возврат
     ИЛИ ДанныеДокумента.ЧекККМПродажа.Пустая() Тогда
        Возврат СтрокиРасхождения;
    КонецЕсли;

    ДокументОснование = ДанныеДокумента.ЧекККМПродажа;
    Запрос = Новый Запрос;

    ТаблицаПоТоварамЗапрос = ТаблицаПоТоварам.Скопировать();
    ТаблицаПоТоварамЗапрос.Свернуть("Номенклатура, ХарактеристикаНоменклатуры, "+РазрезАналитики, "Количество");
    Запрос.УстановитьПараметр("ТаблицаПоТоварам", ТаблицаПоТоварамЗапрос);

    Запрос.Текст = "
    |ВЫБРАТЬ
    |   ТаблицаПоТоварам.Номенклатура,
    |   ТаблицаПоТоварам.ХарактеристикаНоменклатуры,
    |   ТаблицаПоТоварам.Склад,
    |   ТаблицаПоТоварам.Количество КАК Количество
    |   ПОМЕСТИТЬ ЧекККМВозврат
    |ИЗ
    |   &ТаблицаПоТоварам КАК ТаблицаПоТоварам;
    |
    |////////////////////////////////////////////////
    |ВЫБРАТЬ
    |   ЕСТЬNULL(ЧекККМПродажа.Номенклатура, ЧекККМВозврат.Номенклатура) КАК Номенклатура,
    |   ЕСТЬNULL(ЧекККМПродажа.ХарактеристикаНоменклатуры, ЧекККМВозврат.ХарактеристикаНоменклатуры) КАК ХарактеристикаНоменклатуры,
    |   ЕСТЬNULL(ЧекККМПродажа.Номенклатура.ЕдиницаХраненияОстатков, ЧекККМВозврат.Номенклатура.ЕдиницаХраненияОстатков) КАК ЕдиницаХраненияОстатков,
    |   ЕСТЬNULL(ЧекККМПродажа.Склад, ЧекККМВозврат.Склад) КАК Склад,
    |   ЕСТЬNULL(ЧекККМВозврат.Количество, 0) КАК КолвоВозврат,
    |   ЕСТЬNULL(ЧекККМПродажа.Количество, 0) КАК КолвоПродаж,
    |   ВЫБОР
    |       КОГДА ЕСТЬNULL(ЧекККМВозврат.Количество, 0) - ЕСТЬNULL(ЧекККМПродажа.Количество, 0) <= 0
    |           ТОГДА ЛОЖЬ
    |       ИНАЧЕ ИСТИНА
    |   КОНЕЦ КАК Отличаются
    |ИЗ
    |   
    |   (ВЫБРАТЬ
    |       ЕСТЬNULL(ЧекККМТовары.ХарактеристикаНоменклатуры, ВозвращенныеТовары.ХарактеристикаНоменклатуры) КАК ХарактеристикаНоменклатуры,
    |       ЕСТЬNULL(ЧекККМТовары.Номенклатура, ВозвращенныеТовары.Номенклатура) КАК Номенклатура,
    |       ЕСТЬNULL(ЧекККМТовары.Склад, ВозвращенныеТовары.Склад) КАК Склад,
    |       СУММА(ВЫРАЗИТЬ(ЕСТЬNULL(ЧекККМТовары.Количество, 0) - ЕСТЬNULL(ВозвращенныеТовары.Количество, 0) КАК ЧИСЛО(15, 3))) КАК Количество
    |   ИЗ
    |       (ВЫБРАТЬ
    |           ЧекККМТовары.Номенклатура КАК Номенклатура,
    |           ЧекККМТовары.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
    |           ЧекККМТовары.Склад КАК Склад,
    |           ЧекККМТовары.Коэффициент КАК Коэффициент,
    |           СУММА(ЕСТЬNULL(ЧекККМТовары.Количество, 0) * ВЫБОР
    |                   КОГДА ЕСТЬNULL(ЧекККМТовары.Коэффициент, 1) = 0
    |                       ТОГДА 1
    |                   ИНАЧЕ ЕСТЬNULL(ЧекККМТовары.Коэффициент, 1)
    |               КОНЕЦ / ЕСТЬNULL(ЧекККМТовары.Номенклатура.ЕдиницаХраненияОстатков.Коэффициент, 1)) КАК Количество
    |       ИЗ
    |           Документ.ЧекККМ.Товары КАК ЧекККМТовары
    |       ГДЕ
    |           ЧекККМТовары.Ссылка = &ДокументОснование
    |       СГРУППИРОВАТЬ ПО
    |           ЧекККМТовары.Номенклатура,
    |           ЧекККМТовары.ХарактеристикаНоменклатуры,
    |           ЧекККМТовары.Склад,
    |           ЧекККМТовары.Коэффициент) КАК ЧекККМТовары
    |           ПОЛНОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
    |               ЧекККМТовары.Номенклатура КАК Номенклатура,
    |               ЧекККМТовары.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
    |               ЧекККМТовары.Склад КАК Склад,
    |               СУММА(ЧекККМТовары.Количество * ВЫБОР
    |                       КОГДА ЧекККМТовары.Коэффициент = 0
    |                           ТОГДА 1
    |                       ИНАЧЕ ЧекККМТовары.Коэффициент
    |                   КОНЕЦ / ЕСТЬNULL(ЧекККМТовары.Номенклатура.ЕдиницаХраненияОстатков.Коэффициент, 1)) КАК Количество
    |           ИЗ
    |               Документ.ЧекККМ.Товары КАК ЧекККМТовары
    |           ГДЕ
    |               ЧекККМТовары.Ссылка В
    |                       (ВЫБРАТЬ
    |                           Документ.ЧекККМ.Ссылка
    |                       ИЗ
    |                           Документ.ЧекККМ
    |                       ГДЕ
    |                           Документ.ЧекККМ.ЧекККМПродажа = &ДокументОснование
    |                           И (НЕ Документ.ЧекККМ.Ссылка = &ТекущийДокумент)
    |                           И Документ.ЧекККМ.Проведен = ИСТИНА)
    |           СГРУППИРОВАТЬ ПО
    |               ЧекККМТовары.Номенклатура,
    |               ЧекККМТовары.ХарактеристикаНоменклатуры,
    |               ЧекККМТовары.Склад) КАК ВозвращенныеТовары
    |           ПО ЧекККМТовары.ХарактеристикаНоменклатуры = ВозвращенныеТовары.ХарактеристикаНоменклатуры
    |               И ЧекККМТовары.Склад = ВозвращенныеТовары.Склад
    |               И ЧекККМТовары.Номенклатура = ВозвращенныеТовары.Номенклатура
    |   СГРУППИРОВАТЬ ПО
    |       ЕСТЬNULL(ЧекККМТовары.ХарактеристикаНоменклатуры, ВозвращенныеТовары.ХарактеристикаНоменклатуры),
    |       ЕСТЬNULL(ЧекККМТовары.Номенклатура, ВозвращенныеТовары.Номенклатура),
    |       ЕСТЬNULL(ЧекККМТовары.Склад, ВозвращенныеТовары.Склад)) КАК ЧекККМПродажа
    |       ПОЛНОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
    |           ЧекККМВозврат.Номенклатура КАК Номенклатура,
    |           ЧекККМВозврат.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
    |           ЧекККМВозврат.Склад КАК Склад,
    |           СУММА(ВЫРАЗИТЬ(ЧекККМВозврат.Количество КАК ЧИСЛО(15, 3))) КАК Количество
    |       ИЗ
    |           ЧекККМВозврат КАК ЧекККМВозврат
    |       
    |       СГРУППИРОВАТЬ ПО
    |           ЧекККМВозврат.Номенклатура,
    |           ЧекККМВозврат.ХарактеристикаНоменклатуры,
    |           ЧекККМВозврат.Склад) КАК ЧекККМВозврат
    |       ПО ЧекККМПродажа.Номенклатура = ЧекККМВозврат.Номенклатура
    |           И ЧекККМПродажа.ХарактеристикаНоменклатуры = ЧекККМВозврат.ХарактеристикаНоменклатуры
    |           И ЧекККМПродажа.Склад = ЧекККМВозврат.Склад";
    
    Запрос.УстановитьПараметр("ДокументОснование", ДокументОснование);
    Запрос.УстановитьПараметр("ТекущийДокумент", Ссылка);
    Запрос.Текст = СтрЗаменить(Запрос.Текст, "Склад", РазрезАналитики);
    
    Результат = Запрос.Выполнить().Выгрузить();
    
    СтрокиРасхождения = Результат.НайтиСтроки(Новый Структура("Отличаются", Истина));
    
    Возврат СтрокиРасхождения;
    
КонецФункции

// Получает развернутые строки расхождения по оплате при возврате
// 
Функция ПолучитьСтрокиРасхожденияПоОплатеСЧекомПродажи(ДанныеДокумента) Экспорт
    
    СтрокиРасхождения = Новый ТаблицаЗначений;
    
    Если ДанныеДокумента.ВидОперации <> Перечисления.ВидыОперацийЧекККМ.Возврат
     ИЛИ ДанныеДокумента.ЧекККМПродажа.Пустая() Тогда
        Возврат СтрокиРасхождения;
    КонецЕсли;
    
    ДокументОснование = ДанныеДокумента.ЧекККМПродажа;
    
    ТаблицаОплат = Оплата.Выгрузить();
    
    КолвоЭлементов = ТаблицаОплат.Количество();
    
    Для ОбратныйИндекс = 1 По КолвоЭлементов Цикл
        
        СтрокаТаблицыЗначений = ТаблицаОплат[КолвоЭлементов - ОбратныйИндекс];
        Если Не ЗначениеЗаполнено(СтрокаТаблицыЗначений.ВидОплаты)
            ИЛИ СтрокаТаблицыЗначений.ВидОплаты.ТипОплаты = Перечисления.ТипыОплатЧекаККМ.Наличные 
            ИЛИ СтрокаТаблицыЗначений.ВидОплаты = Справочники.ВидыОплатЧекаККМ.ОплатаПодарочнымСертификатом Тогда
            ТаблицаОплат.Удалить(СтрокаТаблицыЗначений);
        КонецЕсли;
        
    КонецЦикла;
    
    Запрос = Новый Запрос;
    Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
    
    Запрос.Текст =
    "ВЫБРАТЬ
    |   ТаблицаПоОплате.ВидОплаты,
    |   ТаблицаПоОплате.Сумма
    |   ПОМЕСТИТЬ ЧекККМВозврат
    |ИЗ
    |   &ТаблицаПоОплате КАК ТаблицаПоОплате";
    
    Запрос.УстановитьПараметр("ТаблицаПоОплате", ТаблицаОплат);
    Запрос.Выполнить();

    Запрос.Текст = 
    "ВЫБРАТЬ
    |   ЕСТЬNULL(ЧекККМПродажа.ВидОплаты, ЧекККМВозврат.ВидОплаты) КАК ВидОплаты,
    |   ЕСТЬNULL(ЧекККМВозврат.Сумма, 0) КАК СуммаВозврат,
    |   ЕСТЬNULL(ЧекККМПродажа.Сумма, 0) КАК СуммаПродаж,
    |   ВЫБОР
    |       КОГДА ЕСТЬNULL(ЧекККМВозврат.Сумма, 0) - ЕСТЬNULL(ЧекККМПродажа.Сумма, 0) = 0
    |           ТОГДА ЛОЖЬ
    |       ИНАЧЕ ИСТИНА
    |   КОНЕЦ КАК Отличаются
    |ИЗ
    |   (ВЫБРАТЬ
    |       ЧекККМОплата.ВидОплаты КАК ВидОплаты,
    |       СУММА(ЧекККМОплата.Сумма) КАК Сумма
    |   ИЗ
    |       Документ.ЧекККМ.Оплата КАК ЧекККМОплата
    |   ГДЕ
    |       ЧекККМОплата.Ссылка = &ДокументОснование
    |       И ЧекККМОплата.ВидОплаты.ТипОплаты <> ЗНАЧЕНИЕ(Перечисление.ТипыОплатЧекаККМ.Наличные)
    |       И (НЕ ЧекККМОплата.ВидОплаты = ЗНАЧЕНИЕ(Справочник.ВидыОплатЧекаККМ.ОплатаПодарочнымСертификатом))
    |   
    |   СГРУППИРОВАТЬ ПО
    |       ЧекККМОплата.ВидОплаты) КАК ЧекККМПродажа
    |       ПОЛНОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
    |           ЧекККМВозврат.ВидОплаты КАК ВидОплаты,
    |           СУММА(ЧекККМВозврат.Сумма) КАК Сумма
    |       ИЗ
    |           ЧекККМВозврат КАК ЧекККМВозврат
    |       
    |       СГРУППИРОВАТЬ ПО
    |           ЧекККМВозврат.ВидОплаты) КАК ЧекККМВозврат
    |       ПО ЧекККМПродажа.ВидОплаты = ЧекККМВозврат.ВидОплаты";
    
    Запрос.УстановитьПараметр("ДокументОснование", ДокументОснование);
    
    Результат = Запрос.Выполнить().Выгрузить();
    
    СтрокиРасхождения = Результат.НайтиСтроки(Новый Структура("Отличаются", Истина));
    
    Возврат СтрокиРасхождения;
    
КонецФункции

// Проверяет правильность заполнения строк табличной части "Оплата".
//
// Параметры:
//  ТаблицаПоОплате         - таблица значений, содержащая данные для проведения и проверки ТЧ Оплата.
//  СтруктураШапкиДокумента - выборка из результата запроса по шапке документа.
//  Отказ                   - флаг отказа в проведении.
//  Заголовок               - заголовок сообщения об ошибках.
//
Процедура ПроверитьЗаполнениеТабличнойЧастиОплата(ТаблицаПоОплате, СтруктураШапкиДокумента, Отказ, Заголовок)
    
    СуммаВсего = Товары.Итог("Сумма");
    ОплаченоНал = ПолучитьСуммуНаличнойОплаты();
    ОплаченоБезнал = ПолучитьСуммуБезналичнойОплаты();
    ОплаченоВсего = Оплата.Итог("Сумма");

    Если ОплаченоВсего < СуммаВсего Тогда
        ОбщегоНазначения.СообщитьОбОшибке("Сумма всех типов оплат меньше суммы документа!", Отказ, Заголовок);
    КонецЕсли;

    Если ОплаченоБезнал > СуммаВсего Тогда
        ОбщегоНазначения.СообщитьОбОшибке("Сумма безналичной оплаты не может быть больше суммы документа!", Отказ, Заголовок);
    КонецЕсли;
    
    Если ВидОперации = Перечисления.ВидыОперацийЧекККМ.Возврат Тогда
        Если Не Оплата.Найти(Справочники.ВидыОплатЧекаККМ.ОплатаПодарочнымСертификатом, "ВидОплаты") = Неопределено Тогда
            ОбщегоНазначения.СообщитьОбОшибке("Чек возврата не оплачивается подарочным сертификатом", Отказ, Заголовок);
        КонецЕсли;
    КонецЕсли;
    
    // Укажем, что надо проверить.
    СтруктураОбязательныхПолей = Новый Структура("ВидОплаты, Сумма");
    Если Не Отказ Тогда
        ОбработкаТабличныхЧастей.ПроверитьЗаполнениеТабличнойЧасти(ЭтотОбъект, "Оплата", СтруктураОбязательныхПолей, Отказ, Заголовок);
    КонецЕсли;
    
КонецПроцедуры // ПроверитьЗаполнениеТабличнойЧастиОплата()

// Процедура проверяет возможность возврата товаров
//
Процедура ПроверитьВозможностьПроведенияЧекаВозврата(ТаблицаПоТоварам, ТаблицаПоОплате, СтруктураШапкиДокумента, Отказ, Результат);

    //Проверка на возможность возврата товаров по остаткам.
    СтрокиРасхождения = ПолучитьСтрокиРасхожденияПоТоварамСЧекомПродажи(ТаблицаПоТоварам, СтруктураШапкиДокумента);

    Для Каждого СтрокаРасхождения Из СтрокиРасхождения Цикл

        Результат = Результат
        + Строка(СтрокаРасхождения.Номенклатура) + УниверсальныеМеханизмы.ПредставлениеХарактеристик(СтрокаРасхождения)
        + " попытка вернуть на склад """ + Строка(СтрокаРасхождения.Склад)+ """: "
        + Строка(СтрокаРасхождения.КолвоВозврат) + " "
        + Строка(СтрокаРасхождения.ЕдиницаХраненияОстатков)
        + ", продано по чеку: " + Строка(СтрокаРасхождения.КолвоПродаж) + " "
        + Строка(СтрокаРасхождения.ЕдиницаХраненияОстатков)
        + Символы.ПС;

        Отказ = Истина;
    
    КонецЦикла;

    //Проверка на возможность возврата товаров по продавцам.
    
    РезультатПродавцы = "";
    
    СтрокиРасхожденияПродавцы = ПолучитьСтрокиРасхожденияПоТоварамСЧекомПродажи(ТаблицаПоТоварам, СтруктураШапкиДокумента, "Продавец");
    
    Для Каждого СтрокаРасхожденияПродавцы Из СтрокиРасхожденияПродавцы Цикл
        
        РезультатПродавцы = РезультатПродавцы
        + Строка(СтрокаРасхожденияПродавцы.Номенклатура) + УниверсальныеМеханизмы.ПредставлениеХарактеристик(СтрокаРасхожденияПродавцы)
        + " попытка оформить возврат на продавца """ + Строка(СтрокаРасхожденияПродавцы.Продавец) + """: "
        + Строка(СтрокаРасхожденияПродавцы.КолвоВозврат) + " "
        + Строка(СтрокаРасхожденияПродавцы.ЕдиницаХраненияОстатков)
        + ", было продано продавцом: " + Строка(СтрокаРасхожденияПродавцы.КолвоПродаж) + " "
        + Строка(СтрокаРасхожденияПродавцы.ЕдиницаХраненияОстатков)
        + Символы.ПС;
        
        Отказ = Истина;
        
    КонецЦикла;

    //Проверка на возможность возврата товаров по оплате.
    СтрокиРасхожденияОплата = ПолучитьСтрокиРасхожденияПоОплатеСЧекомПродажи(СтруктураШапкиДокумента);
    РезультатОплата = "";

    Для Каждого СтрокаРасхожденияОплата Из СтрокиРасхожденияОплата Цикл

        РезультатОплата = РезультатОплата
        + Строка(СтрокаРасхожденияОплата.ВидОплаты)
        + " попытка вернуть: " + ОбщегоНазначения.ФорматСумм(СтрокаРасхожденияОплата.СуммаВозврат,,"0")
        + ", оплачено по чеку: " + ОбщегоНазначения.ФорматСумм(СтрокаРасхожденияОплата.СуммаПродаж,,"0") + Символы.ПС;

        Отказ = Истина;
    
    КонецЦикла;
    
    Результат = Результат + РезультатПродавцы + РезультатОплата;

КонецПроцедуры

// По результату запроса по шапке документа формируем движения по регистрам.

//

// Параметры: 

//  РежимПроведения           - режим проведения документа (оперативный или неоперативный),

//  СтруктураШапкиДокумента   - выборка из результата запроса по шапке документа,

//  ТаблицаПоТоварам          - таблица значений, содержащая данные для проведения и проверки ТЧ Товары

//  ТаблицаСерийныхНомеров    - таблица значений для проведения сертификатов
//  ТаблицаПодарочныхСертификатовПогашения - таблица значений для проведения погашения
//  Отказ                     - флаг отказа в проведении,

//  Заголовок                 - строка, заголовок сообщения об ошибке проведения.

//

Процедура ДвиженияПоРегистрам(РежимПроведения, СтруктураШапкиДокумента, ТаблицаПоТоварам, ТаблицаПоКомплектам, ТаблицаПоТоварамБезУслугБезКомплектов, 
                              ТаблицаПоОплате, ТаблицаПодарки, ТаблицаСерийныхНомеров, ТаблицаПодарочныхСертификатовПогашения, Отказ, Заголовок);

    

    Если Отказ тогда

        Возврат;

    КонецЕсли;
    
    Если СтруктураШапкиДокумента.ВидОперации <> Перечисления.ВидыОперацийЧекККМ.Возврат Тогда

        
        Если Не ПроцедурыОбменаДаннымиПоКассе.ЭтоУзелКассы() Тогда
            
            // ТОВАРЫ НА СКЛАДАХ

            НаборДвижений = Движения.ТоварыНаСкладах;

            // Получим таблицу значений, совпадающую со структурой набора записей регистра.

            ТаблицаДвижений = НаборДвижений.ВыгрузитьКолонки();

            

            ОбщегоНазначения.ЗагрузитьВТаблицуЗначений(ТаблицаПоТоварамБезУслугБезКомплектов, ТаблицаДвижений);

            НаборДвижений.мПериод          = Дата;

            НаборДвижений.мТаблицаДвижений = ТаблицаДвижений;

            НаборДвижений.ВыполнитьРасход();

            

            // ТОВАРЫ НА СКЛАДАХ для комплектующих

            НаборДвижений = Движения.ТоварыНаСкладах;

            // Получим таблицу значений, совпадающую со структурой набора записей регистра.

            ТаблицаДвижений = НаборДвижений.ВыгрузитьКолонки();

            

            ОбщегоНазначения.ЗагрузитьВТаблицуЗначений(ТаблицаПоКомплектам, ТаблицаДвижений);

            НаборДвижений.мПериод          = Дата;

            НаборДвижений.мТаблицаДвижений = ТаблицаДвижений;

            НаборДвижений.ВыполнитьРасход();

            

            // ПРОДАЖИ

            НаборДвижений = Движения.Продажи;

            // Получим таблицу значений, совпадающую со структурой набора записей регистра.

            ТаблицаДвижений = НаборДвижений.Выгрузить();

            ОбщегоНазначения.ЗагрузитьВТаблицуЗначений(ТаблицаПоТоварам, ТаблицаДвижений);
            ТаблицаДвижений.ЗаполнитьЗначения(Ссылка,"ДокументПродажи");

            
            НаборДвижений.мПериод          = Дата;
            НаборДвижений.мТаблицаДвижений = ТаблицаДвижений;

            НаборДвижений.ВыполнитьДвижения();
            
            //ПОДАРКИ
            НаборДвижений = Движения.ТоварыНаСкладах;
            // Получим таблицу значений, совпадающую со структурой набора записей регистра.
            ТаблицаДвижений = НаборДвижений.ВыгрузитьКолонки();
            
            ОбщегоНазначения.ЗагрузитьВТаблицуЗначений(ТаблицаПодарки, ТаблицаДвижений);
            НаборДвижений.мПериод          = Дата;
            НаборДвижений.мТаблицаДвижений = ТаблицаДвижений;
            НаборДвижений.ВыполнитьРасход();
        КонецЕсли;
        

        Если ЗначениеЗаполнено(СтруктураШапкиДокумента.СуммаНаличными)  Тогда
            //По "Денежные Средства"
            НаборДвиженийОстатки   = Движения.ДенежныеСредства;
            ТаблицаДвиженийОстатки = НаборДвиженийОстатки.Выгрузить();
            
            СтрокаДвиженийОстатки = ТаблицаДвиженийОстатки.Добавить();
            СтрокаДвиженийОстатки.Касса = СтруктураШапкиДокумента.КассаККМ;
            СтрокаДвиженийОстатки.Сумма = СтруктураШапкиДокумента.СуммаНаличными;
            
            НаборДвиженийОстатки.мПериод          = Дата;
            НаборДвиженийОстатки.мТаблицаДвижений = ТаблицаДвиженийОстатки;
            Движения.ДенежныеСредства.ВыполнитьПриход();
        КонецЕсли;
        
        //По Дисконтным картам
        Если Не СтруктураШапкиДокумента.ДисконтнаяКарта.Пустая() Тогда

            НаборДвижений   = Движения.ПродажиПоДисконтнымКартам;
            ТаблицаДвижений = НаборДвижений.Выгрузить();
            ОбщегоНазначения.ЗагрузитьВТаблицуЗначений(ТаблицаПоТоварам, ТаблицаДвижений);
            ТаблицаДвижений.ЗаполнитьЗначения(СтруктураШапкиДокумента.ДисконтнаяКарта        , "ДисконтнаяКарта");
            ТаблицаДвижений.ЗаполнитьЗначения(СтруктураШапкиДокумента.ВладелецДисконтнойКарты, "ВладелецДисконтнойКарты");
            
            НаборДвижений.мПериод          = Дата;
            НаборДвижений.мТаблицаДвижений = ТаблицаДвижений;
            НаборДвижений.ВыполнитьДвижения();
        КонецЕсли;
        
        //По платежным картам
        Если Не ТаблицаПоОплате.Количество() = 0 Тогда
            НаборДвижений   = Движения.ПродажиПоПлатежнымКартам;

            ТаблицаДвижений = НаборДвижений.Выгрузить();

            ОбщегоНазначения.ЗагрузитьВТаблицуЗначений(ТаблицаПоОплате, ТаблицаДвижений);
        

            НаборДвижений.мПериод          = Дата;

            НаборДвижений.мТаблицаДвижений = ТаблицаДвижений;

            НаборДвижений.ВыполнитьДвижения();
        КонецЕсли;
        
        Если НЕ ТаблицаСерийныхНомеров.Количество() = 0 ИЛИ НЕ ТаблицаПодарочныхСертификатовПогашения.Количество() = 0 Тогда
            //Сертификаты
            НаборДвижений = Движения.ДвиженияСерийныхНомеров;
            ТаблицаДвижений = НаборДвижений.Выгрузить();

            ТаблицаСерийныхНомеров.Колонки.Склад.Имя = "Отправитель";
            // Заполним таблицу движений.
            ОбщегоНазначения.ЗагрузитьВТаблицуЗначений(ТаблицаСерийныхНомеров, ТаблицаДвижений);
            ТаблицаДвижений.ЗаполнитьЗначения(Справочники.ХозяйственныеОперации.РеализацияТоваров, "ХозяйственнаяОперация");

            ТаблицаПодарочныхСертификатовПогашения.Колонки.ПодарочныйСертификат.Имя = "Номенклатура";
            ОбщегоНазначения.ЗагрузитьВТаблицуЗначений(ТаблицаПодарочныхСертификатовПогашения, ТаблицаДвижений);
            
            НаборДвижений.мПериод          = Дата;
            НаборДвижений.мТаблицаДвижений = ТаблицаДвижений;

            Если Не Отказ Тогда
                Движения.ДвиженияСерийныхНомеров.ВыполнитьДвижения();
            КонецЕсли;
        КонецЕсли;
        
    Иначе

        
        Если Не ПроцедурыОбменаДаннымиПоКассе.ЭтоУзелКассы() Тогда
            
            // ТОВАРЫ НА СКЛАДАХ

            НаборДвижений = Движения.ТоварыНаСкладах;

            // Получим таблицу значений, совпадающую со структурой набора записей регистра.

            ТаблицаДвижений = НаборДвижений.ВыгрузитьКолонки();

            

            ОбщегоНазначения.ЗагрузитьВТаблицуЗначений(ТаблицаПоТоварамБезУслугБезКомплектов, ТаблицаДвижений);

            НаборДвижений.мПериод          = Дата;

            НаборДвижений.мТаблицаДвижений = ТаблицаДвижений;

            НаборДвижений.ВыполнитьПриход();

            

            // ТОВАРЫ НА СКЛАДАХ для комплектующих

            НаборДвижений = Движения.ТоварыНаСкладах;

            // Получим таблицу значений, совпадающую со структурой набора записей регистра.

            ТаблицаДвижений = НаборДвижений.ВыгрузитьКолонки();

            

            ОбщегоНазначения.ЗагрузитьВТаблицуЗначений(ТаблицаПоКомплектам, ТаблицаДвижений);

            НаборДвижений.мПериод          = Дата;

            НаборДвижений.мТаблицаДвижений = ТаблицаДвижений;

            НаборДвижений.ВыполнитьПриход();

            

            // ПРОДАЖИ

            НаборДвижений = Движения.Продажи;

            // Получим таблицу значений, совпадающую со структурой набора записей регистра.

            ТаблицаДвижений = НаборДвижений.Выгрузить();

            ТаблицаПотоварам.Колонки.Удалить("Стоимость");

            ТаблицаПотоварам.Колонки.Удалить("СтоимостьБезСкидок");

            ТаблицаПотоварам.Колонки.Удалить("Количество");

            ТаблицаПотоварам.Колонки.Удалить("НДС");
            ТаблицаПоТоварам.Колонки.Удалить("Сумма");
            ТаблицаПоТоварам.Колонки.СтоимостьМинус.Имя          = "Стоимость"; 

            ТаблицаПоТоварам.Колонки.СтоимостьБезСкидокМинус.Имя = "СтоимостьБезСкидок"; 

            ТаблицаПоТоварам.Колонки.КоличествоМинус.Имя         = "Количество"; 

            ТаблицаПоТоварам.Колонки.НДСМинус.Имя                = "НДС";
            ТаблицаПоТоварам.Колонки.СуммаМинус.Имя              = "Сумма";
            

            ОбщегоНазначения.ЗагрузитьВТаблицуЗначений(ТаблицаПоТоварам, ТаблицаДвижений);

            ТаблицаДвижений.ЗаполнитьЗначения(Ссылка,"ДокументПродажи");

            

            НаборДвижений.мПериод          = Дата;

            НаборДвижений.мТаблицаДвижений = ТаблицаДвижений;

            НаборДвижений.ВыполнитьДвижения();

            
            //ПОДАРКИ
            НаборДвижений = Движения.ТоварыНаСкладах;
            // Получим таблицу значений, совпадающую со структурой набора записей регистра.
            ТаблицаДвижений = НаборДвижений.ВыгрузитьКолонки();
            
            ОбщегоНазначения.ЗагрузитьВТаблицуЗначений(ТаблицаПодарки, ТаблицаДвижений);
            НаборДвижений.мПериод          = Дата;
            НаборДвижений.мТаблицаДвижений = ТаблицаДвижений;
            НаборДвижений.ВыполнитьПриход();
        Иначе
            ТаблицаПотоварам.Колонки.Удалить("Стоимость");
            ТаблицаПотоварам.Колонки.Удалить("СтоимостьБезСкидок");
            ТаблицаПотоварам.Колонки.Удалить("Количество");
            ТаблицаПотоварам.Колонки.Удалить("НДС");
            ТаблицаПоТоварам.Колонки.Удалить("Сумма");
            ТаблицаПоТоварам.Колонки.СтоимостьМинус.Имя          = "Стоимость"; 
            ТаблицаПоТоварам.Колонки.СтоимостьБезСкидокМинус.Имя = "СтоимостьБезСкидок"; 
            ТаблицаПоТоварам.Колонки.КоличествоМинус.Имя         = "Количество"; 
            ТаблицаПоТоварам.Колонки.НДСМинус.Имя                = "НДС";
            ТаблицаПоТоварам.Колонки.СуммаМинус.Имя              = "Сумма";
        КонецЕсли;
        

        Если ЗначениеЗаполнено(СтруктураШапкиДокумента.СуммаНаличными)  Тогда
            //По "Денежные Средства"
            НаборДвиженийОстатки   = Движения.ДенежныеСредства;
            ТаблицаДвиженийОстатки = НаборДвиженийОстатки.Выгрузить();
            
            СтрокаДвиженийОстатки = ТаблицаДвиженийОстатки.Добавить();
            СтрокаДвиженийОстатки.Касса = СтруктураШапкиДокумента.КассаККМ;
            СтрокаДвиженийОстатки.Сумма = СтруктураШапкиДокумента.СуммаНаличными;
            
            НаборДвиженийОстатки.мПериод          = Дата;
            НаборДвиженийОстатки.мТаблицаДвижений = ТаблицаДвиженийОстатки;
            Движения.ДенежныеСредства.ВыполнитьРасход();
        КонецЕсли;
        
        //По Дисконтным картам
        Если Не СтруктураШапкиДокумента.ДисконтнаяКарта.Пустая() Тогда
            НаборДвижений   = Движения.ПродажиПоДисконтнымКартам;
            ТаблицаДвижений = НаборДвижений.Выгрузить();
            ОбщегоНазначения.ЗагрузитьВТаблицуЗначений(ТаблицаПоТоварам, ТаблицаДвижений);
            ТаблицаДвижений.ЗаполнитьЗначения(СтруктураШапкиДокумента.ДисконтнаяКарта        , "ДисконтнаяКарта");
            ТаблицаДвижений.ЗаполнитьЗначения(СтруктураШапкиДокумента.ВладелецДисконтнойКарты, "ВладелецДисконтнойКарты");
            
            НаборДвижений.мПериод          = Дата;
            НаборДвижений.мТаблицаДвижений = ТаблицаДвижений;
            НаборДвижений.ВыполнитьДвижения();
        КонецЕсли;

        //По платежным картам
        Если Не ТаблицаПоОплате.Количество() = 0 Тогда

            НаборДвижений   = Движения.ПродажиПоПлатежнымКартам;

            ТаблицаДвижений = НаборДвижений.Выгрузить();
        
            ТаблицаПоОплате.Колонки.Удалить("Сумма");
            ТаблицаПоОплате.Колонки.СуммаМинус.Имя = "Сумма";
        
            ТаблицаПоОплате.Колонки.Удалить("СуммаТорговойУступки");
        
            Если СтруктураШапкиДокумента.ДоговорЭквайринга.ЭквайрерВозвращаетКомиссиюПриВозврате Тогда
                ТаблицаПоОплате.Колонки.СуммаТорговойУступкиМинус.Имя = "СуммаТорговойУступки";
            КонецЕсли;
        

            ОбщегоНазначения.ЗагрузитьВТаблицуЗначений(ТаблицаПоОплате, ТаблицаДвижений);

        

            НаборДвижений.мПериод          = Дата;

            НаборДвижений.мТаблицаДвижений = ТаблицаДвижений;

            НаборДвижений.ВыполнитьДвижения();
        КонецЕсли;
        
        

    КонецЕсли;

    

КонецПроцедуры // ДвиженияПоРегистрам()


// Проверяет доступный остаток товаров по складу
//
Процедура ПроверитьОстаткиТоваров(Дата, РежимПроведения, ТаблицаПоТоварамБезУслугБезКомплектов, ТаблицаПоКомплектам, Отказ, Заголовок, Результат) Экспорт

    Если (РежимРМК И Не КонтролироватьОстаткиТоваровПриЗакрытииЧека)
     ИЛИ ПроцедурыОбменаДаннымиПоКассе.ЭтоУзелКассы() Тогда
        Возврат;
    КонецЕсли;
    
    ТаблицаОбщаяДляПроверкиОстатков = ТаблицаПоТоварамБезУслугБезКомплектов.Скопировать();
    ОбщегоНазначения.ЗагрузитьВТаблицуЗначений(ТаблицаПоКомплектам, ТаблицаОбщаяДляПроверкиОстатков);
    УправлениеЗапасами.ПроверитьОстаткиПоСкладам(Дата, РежимПроведения, ТаблицаОбщаяДляПроверкиОстатков, Отказ, Заголовок, Результат);
    УправлениеЗапасами.ПроверитьОстаткиСерийныхНомеров(ЭтотОбъект, ТаблицаПоТоварамБезУслугБезКомплектов, "СерийныеНомера", РежимПроведения, Отказ, Заголовок, Результат, ,Дата);
    
КонецПроцедуры

// Процедура добавляет необходимые поля в таблицу по товарам.
//
Процедура ПодготовитьТаблицуТоваров(ТаблицаТоваров, СтруктураШапкиДокумента)
    
    ТаблицаТоваров.Колонки.Добавить("Стоимость"         , ОбщегоНазначения.ПолучитьОписаниеТиповЧисла(15,2));
    ТаблицаТоваров.Колонки.Добавить("СтоимостьБезСкидок", ОбщегоНазначения.ПолучитьОписаниеТиповЧисла(15,2));
    
    ТаблицаТоваров.Колонки.Добавить("СтоимостьМинус"         , ОбщегоНазначения.ПолучитьОписаниеТиповЧисла(15,2));
    ТаблицаТоваров.Колонки.Добавить("СтоимостьБезСкидокМинус", ОбщегоНазначения.ПолучитьОписаниеТиповЧисла(15,2));
    
    ТаблицаТоваров.Колонки.Добавить("СуммаМинус", ОбщегоНазначения.ПолучитьОписаниеТиповЧисла(15,2));
    
    Для Каждого СтрокаТаблицы Из ТаблицаТоваров Цикл
    
        СтрокаТаблицы.Стоимость = СтрокаТаблицы.Сумма;
        
        СтрокаТаблицы.СтоимостьБезСкидок = СтрокаТаблицы.Цена * СтрокаТаблицы.КоличествоТЧ;
        
        СтрокаТаблицы.СтоимостьМинус          = - СтрокаТаблицы.Стоимость;
        СтрокаТаблицы.СтоимостьБезСкидокМинус = - СтрокаТаблицы.СтоимостьБезСкидок;
        
        СтрокаТаблицы.СуммаМинус = - СтрокаТаблицы.Сумма;
    КонецЦикла;
    
КонецПроцедуры

// Проверяет правильность заполнения строк табличной части "Подарки".
//
// Параметры:
//  ТаблицаПодарки          - таблица значений, содержащая данные для проведения и проверки ТЧ Подарки.
//  СтруктураШапкиДокумента - выборка из результата запроса по шапке документа.
//  Отказ                   - флаг отказа в проведении.
//  Заголовок               - заголовок сообщения об ошибках.
//
Процедура ПроверитьЗаполнениеТабличнойЧастиПодарки(ТаблицаПодарки, СтруктураШапкиДокумента, Отказ, Заголовок)

    ИмяТабличнойЧасти = "Подарки";

    // Укажем, что надо проверить:
    СтруктураОбязательныхПолей = Новый Структура("Номенклатура, ХарактеристикаНоменклатуры, Количество, Склад");

    // Теперь позовем общую процедуру проверки.
    ОбработкаТабличныхЧастей.ПроверитьЗаполнениеТабличнойЧасти(ЭтотОбъект, "Подарки", СтруктураОбязательныхПолей, Отказ, Заголовок);
    
    //Подарочных сертификатов здесь быть не должно
    УправлениеЗапасами.ПроверитьЧтоНетПодарочныхСертификатов(ЭтотОбъект, "Подарки", , Отказ, Заголовок);
    
    
КонецПроцедуры // ПроверитьЗаполнениеТабличнойЧастиТовары()


// Подготавливает таблицу погашения
//
// Параметры
//  Нет
//
// Возвращаемое значение:
//   <Тип.Вид>   - <описание возвращаемого значения>
//
Функция ПодготовитьТаблицуПогашения() Экспорт

    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
    |   ТаблицаПогашения.НомерСтроки,
    |   ТаблицаПогашения.ПодарочныйСертификат,
    |   ТаблицаПогашения.СерийныйНомер
    |ПОМЕСТИТЬ ТаблицаВЗапросе
    |ИЗ
    |   &ТаблицаПогашения КАК ТаблицаПогашения
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |   ТаблицаВЗапросе.НомерСтроки,
    |   ТаблицаВЗапросе.ПодарочныйСертификат.ПодарочныйСертификат КАК НоменклатураПодарочныйСертификат,
    |   ТаблицаВЗапросе.ПодарочныйСертификат.ВестиСерийныеНомера КАК НоменклатураВестиСерийныеНомера,
    |   ТаблицаВЗапросе.ПодарочныйСертификат,
    |   ТаблицаВЗапросе.СерийныйНомер,
    |   ЗНАЧЕНИЕ(Справочник.ХозяйственныеОперации.ПогашениеПодарочныхСертификатов) КАК ХозяйственнаяОперация,
    |   1 КАК Количество,
    |   &Склад КАК Получатель
    |ИЗ
    |   ТаблицаВЗапросе КАК ТаблицаВЗапросе";
    
    Запрос.УстановитьПараметр("ТаблицаПогашения", ПогашениеПодарочныхСертификатов.Выгрузить());
    Запрос.УстановитьПараметр("Склад", Магазин.ОсновнойСклад);
    
    Результат = Запрос.Выполнить();
    ТаблицаЗапроса = Результат.Выгрузить();
    
    Возврат ТаблицаЗапроса;

КонецФункции // ПодготовитьТаблицуПогашения()


// Проверяет правильность заполнения строк табличной части "ПогашениеПодарочныхСертификатов".
//
// Параметры: 
//  ТаблицаПогашения        - таблица значений, содержащая данные для проведения и проверки ТЧ ПогашениеПодарочныхСертификатов,
//  СтруктураШапкиДокумента - выборка из результата запроса по шапке документа,
//  Отказ                   - флаг отказа в проведении,
//  Заголовок               - строка, заголовок сообщения об ошибке проведения.
//
Процедура ПроверитьЗаполнениеТабличнойЧастиПогашения(ТаблицаПогашения, СтруктураШапкиДокумента, Отказ, Заголовок) Экспорт

    // Проверить заполнение ТЧ "Состав набора".
    СтруктураОбязательныхПолей = Новый Структура("ПодарочныйСертификат");
    
    ОбработкаТабличныхЧастей.ПроверитьЗаполнениеТабличнойЧасти(ЭтотОбъект, "ПогашениеПодарочныхСертификатов", СтруктураОбязательныхПолей, Отказ, Заголовок);
    
    Если Не Отказ Тогда
        
        СтруктураПоиска = Новый Структура;
        СтруктураПоиска.Вставить("НоменклатураВестиСерийныеНомера", Истина);
        СтруктураПоиска.Вставить("СерийныйНомер", Справочники.СерийныеНомера.ПустаяСсылка());
        
        МассивСтрок = ТаблицаПогашения.НайтиСтроки(СтруктураПоиска);
        
        
        Для каждого СтрокаТаблицыПогашения Из МассивСтрок Цикл
            СтрокаНачалаСообщенияОбОшибке = "В строке номер """+ СокрЛП(СтрокаТаблицыПогашения.НомерСтроки) +
                                           """ табличной части ""Погашение подарочных сертификатов"": ";
            
            СтрокаСообщения = " не заполнен серийный номер сертификата";
            ОбщегоНазначения.СообщитьОбОшибке(СтрокаНачалаСообщенияОбОшибке + СтрокаСообщения, Отказ, Заголовок);
        КонецЦикла;
        
        Если Не Отказ Тогда
            СтруктураПоиска = Новый Структура;
            СтруктураПоиска.Вставить("НоменклатураПодарочныйСертификат", Ложь);
            
            МассивСтрок = ТаблицаПогашения.НайтиСтроки(СтруктураПоиска);
            Для каждого СтрокаТаблицыПогашения Из МассивСтрок Цикл
                СтрокаНачалаСообщенияОбОшибке = "В строке номер """+ СокрЛП(СтрокаТаблицыПогашения.НомерСтроки) +
                                               """ табличной части ""Погашение подарочных сертификатов"": ";
                
                СтрокаСообщения = " выбранная номенклатура не является подарочным сертификатом ";
                ОбщегоНазначения.СообщитьОбОшибке(СтрокаНачалаСообщенияОбОшибке + СтрокаСообщения, Отказ, Заголовок);
            КонецЦикла;
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры // ПроверитьЗаполнениеТабличнойЧастиПогашения()

////////////////////////////////////////////////////////////////////////////////
// ОБРАБОТЧИКИ СОБЫТИЙ

// Процедура - обработчик события "ПередЗаписью".
//
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    
    мЗакрытиеСмены = (Не ЗначениеЗаполнено(Ссылка.ОтчетОРозничныхПродажах)
                     И  ЗначениеЗаполнено(ОтчетОРозничныхПродажах));
    
    Если ОбменДанными.Загрузка
     ИЛИ РольДоступна("ПолныеПрава") Тогда
        Возврат;
    КонецЕсли;
    
    Если Не РежимРМК
     И Ссылка.СтатусЧекаККМ = Перечисления.СтатусыЧековККМ.Отложенный Тогда
        
        СтатусЧекаККМ = Перечисления.СтатусыЧековККМ.ПустаяСсылка();
        
    КонецЕсли;
    
    Если (Ссылка.СтатусЧекаККМ = Перечисления.СтатусыЧековККМ.Пробитый
     И Не мЗакрытиеСмены)
     ИЛИ Ссылка.СтатусЧекаККМ = Перечисления.СтатусыЧековККМ.Архивный
     ИЛИ Ссылка.СтатусЧекаККМ = Перечисления.СтатусыЧековККМ.Аннулированный Тогда
    
        ОбщегоНазначения.СообщитьОбОшибке("Чек ККМ имеет статус """ + СтатусЧекаККМ +""". Операции над этим документом запрещены!", Отказ, СокрЛП(ЭтотОбъект));
    
    КонецЕсли;
    
КонецПроцедуры

// Процедура - обработчик события "ОбработкаЗаполнения".
//
Процедура ОбработкаЗаполнения(Основание)

        
    Если ТипЗнч(Основание) = Тип("ДокументСсылка.ЧекККМ") Тогда
        
        ОбработкаТабличныхЧастей.ЗаполнитьТабЧастьНаОсновании(ЭтотОбъект, Основание);
        
        ЗаполнитьЗначенияСвойств(ЭтотОбъект, Основание, "ВладелецДисконтнойКарты, ДисконтнаяКарта, КассаККМ, СуммаДокумента, Магазин, ДоговорЭквайринга, Продавец");
        
        ЧекККМПродажа   = Основание;
        ВидОперации     = Перечисления.ВидыОперацийЧекККМ.Возврат;
        ДисконтнаяКарта = Основание.ДисконтнаяКарта;
        
        ВладелецДисконтнойКарты = Основание.ВладелецДисконтнойКарты;
        
        СерийныеНомера.Очистить();
        ПогашениеПодарочныхСертификатов.Очистить();
        
        УправлениеЗапасами.УдалитьПодарочныеСертификаты(Товары);
        
        КолвоЭлементовКоллекции = Оплата.Количество();
        Для ОбратныйИндекс = 1 По КолвоЭлементовКоллекции Цикл
            ЭлементКоллекции = Оплата[КолвоЭлементовКоллекции - ОбратныйИндекс];

            Если ЭлементКоллекции.ВидОплаты = Справочники.ВидыОплатЧекаККМ.ОплатаПодарочнымСертификатом Тогда
                Оплата.Удалить(ЭлементКоллекции);
            КонецЕсли;
        КонецЦикла;
        
        
    ИначеЕсли ТипЗнч(Основание) = Тип("ДокументСсылка.ОприходованиеТоваров") Тогда
        
        ОбработкаТабличныхЧастей.ЗаполнитьТабЧастьНаОсновании(ЭтотОбъект, Основание);
        
        Для Каждого ТекСтрокаТовары Из Товары Цикл
            ТекСтрокаТовары.Склад = Основание.Склад;
        КонецЦикла;
        
    КонецЕсли;
    
КонецПроцедуры


// Процедура - обработчик события "ОбработкаПроведения".
//
Процедура ОбработкаПроведения(Отказ, РежимПроведения)

    Если мЗакрытиеСмены Тогда
        Возврат;
    КонецЕсли;
    
    
    Результат = "";

    СтруктураШапкиДокумента = УправлениеЗапасами.СформироватьСтруктуруШапкиДокумента(ЭтотОбъект);
    
    // Заголовок для сообщений об ошибках проведения.
    Заголовок = ОбщегоНазначения.ПредставлениеДокументаПриПроведении(СтруктураШапкиДокумента);
    
    СуммаНаличными = Макс(0, СуммаДокумента - ПолучитьСуммуБезналичнойОплаты() - ПолучитьСуммуОплатыПодарочнымиСертификатами());
    СтруктураШапкиДокумента.Вставить("СуммаНаличными", СуммаНаличными);

    ПроверитьЗаполнениеШапки(СтруктураШапкиДокумента, Отказ, Заголовок);
    
    //Формирует структуру для подстановки в цикл формирования запроса
    СтруктураПолей = УправлениеЗапасами.СформироватьСтруктуруПолейТабличнойЧасти(ЭтотОбъект, "Товары");
    СтруктураПолей.Количество = 
    "Количество *
    |   ВЫБОР
    |       КОГДА ЕдиницаИзмерения = ЗНАЧЕНИЕ(Справочник.ЕдиницыИзмерения.ПустаяСсылка)
    |           ТОГДА 1
    |       ИНАЧЕ
    |           Коэффициент /ЕСТЬNULL(Номенклатура.ЕдиницаХраненияОстатков.Коэффициент, 1)
    |   КОНЕЦ
    |";
    
    СтруктураПолей.Вставить("НДС",             "СуммаНДС");
    СтруктураПолей.Вставить("Магазин",         "Склад.Магазин");
    СтруктураПолей.Вставить("ТипСклада",       "Склад.ТипСклада");
    СтруктураПолей.Вставить("Организация",     "Склад.Организация");
    СтруктураПолей.Вставить("КоличествоТЧ",    "Количество");
    
    //для возврата
    СтруктураПолей.Вставить("Услуга"  ,        "Номенклатура.Услуга");
    СтруктураПолей.Вставить("НДСМинус",        "СуммаНДС * -1");
    СтруктураПолей.Вставить("Комплект",        "Номенклатура.Комплект");
    СтруктураПолей.Вставить("КоличествоМинус", "Количество * -1 * 
    |   ВЫБОР
    |       КОГДА ЕдиницаИзмерения = ЗНАЧЕНИЕ(Справочник.ЕдиницыИзмерения.ПустаяСсылка)
    |           ТОГДА 1
    |       ИНАЧЕ
    |           Коэффициент /ЕСТЬNULL(Номенклатура.ЕдиницаХраненияОстатков.Коэффициент, 1)
    |   КОНЕЦ
    |");
    
    СтруктураСложныхПолей = Новый Структура;
    Если ВидОперации = Перечисления.ВидыОперацийЧекККМ.Возврат Тогда
        
        СтруктураПолей.Вставить("ХозяйственнаяОперация", "Ссылка.ХозяйственнаяОперация");
    Иначе
        СтруктураСложныхПолей.Вставить("ХозяйственнаяОперация", "ЗНАЧЕНИЕ(Справочник.ХозяйственныеОперации.РеализацияТоваров)");
    КонецЕсли;
    
    //Формирует список дополнительных условий запроса
    СписокУсловийЗапроса = Новый СписокЗначений;
    СписокУсловийЗапроса.Добавить(Перечисления.ТипыСкладов.СкладЦентральногоОфиса, "Склад.ТипСклада", Ложь);
    
    РезультатЗапросаПоТоварам = УправлениеЗапасами.СформироватьЗапросПоТабличнойЧасти(ЭтотОбъект, "Товары", СтруктураПолей, СтруктураСложныхПолей, СписокУсловийЗапроса);
    
    ТаблицаПоТоварам = РезультатЗапросаПоТоварам.Выгрузить();
    
    ПодготовитьТаблицуТоваров(ТаблицаПоТоварам, СтруктураШапкиДокумента);

    //получим таблицу комплектующих
    ТаблицаПоКомплектам                   = УправлениеЗапасами.СформироватьТаблицуКомплектующих(ТаблицаПоТоварам, ЭтотОбъект, СтруктураШапкиДокумента);
    ТаблицаПоТоварамБезУслугБезКомплектов = УправлениеЗапасами.УдалитьУслугиКомплектыИзТаблицыТоваров(ТаблицаПоТоварам);
    
    ПроверитьЗаполнениеТабличнойЧастиТовары(ТаблицаПоТоварам, СтруктураШапкиДокумента, Отказ, Заголовок, Результат);
    ПроверитьЗаполнениеТабличнойЧастиСоставНабора(ТаблицаПоКомплектам, СтруктураШапкиДокумента, Отказ, Заголовок, Результат);
    
    //Оплата
    СтруктураПолейОплата     = Новый Структура;
    СтруктураПолейОплата.Вставить("СуммаМинус",     "Сумма * -1");
    СтруктураПолейОплата.Вставить("СуммаТорговойУступкиМинус",     "СуммаТорговойУступки * -1");
    СтруктураПолейОплата.Вставить("ДоговорЭквайринга", "Ссылка.ДоговорЭквайринга");
    СтруктураПолейОплата.Вставить("Магазин",     "Ссылка.Магазин");
    РезультатЗапросаПоОплате = Эквайринг.СформироватьЗапросПоОплате(ЭтотОбъект, "Оплата", СтруктураПолейОплата);
    ТаблицаПоОплате          = РезультатЗапросаПоОплате.Выгрузить();
    ПроверитьЗаполнениеТабличнойЧастиОплата(ТаблицаПоОплате, СтруктураШапкиДокумента, Отказ, Заголовок);
    
    
    // Подарки
    
    СтруктураПолейПодарки   = УправлениеЗапасами.СформироватьСтруктуруПолейТабличнойЧасти(ЭтотОбъект, "Подарки");
    СтруктураПолейПодарки.Вставить("Магазин"         ,"Ссылка.КассаККМ.Магазин");
    СтруктураПолейПодарки.Вставить("ЕдиницаИзмерения","Номенклатура.ЕдиницаХраненияОстатков");
    СтруктураПолейПодарки.Количество = 
    "Количество *
    |   ВЫБОР
    |       КОГДА ЕдиницаИзмерения = ЗНАЧЕНИЕ(Справочник.ЕдиницыИзмерения.ПустаяСсылка)
    |           ТОГДА 1
    |       ИНАЧЕ
    |           Коэффициент /ЕСТЬNULL(Номенклатура.ЕдиницаХраненияОстатков.Коэффициент, 1)
    |   КОНЕЦ
    |";
    
    
    СтруктураПолейПодарки.Вставить("КоличествоМинус","Количество * -1 *
    |   ВЫБОР
    |       КОГДА ЕдиницаИзмерения = ЗНАЧЕНИЕ(Справочник.ЕдиницыИзмерения.ПустаяСсылка)
    |           ТОГДА 1
    |       ИНАЧЕ
    |           Коэффициент /ЕСТЬNULL(Номенклатура.ЕдиницаХраненияОстатков.Коэффициент, 1)
    |   КОНЕЦ
    |");
    
    
    СписокУсловийПодарки = Новый СписокЗначений;
    СписокУсловийПодарки.Добавить(Перечисления.ТипыСкладов.СкладЦентральногоОфиса, "Склад.ТипСклада", Ложь);
    
    СтруктураСложныхПолей = Новый Структура;
    СтруктураСложныхПолей.Вставить("ХозяйственнаяОперация", "ЗНАЧЕНИЕ(Справочник.ХозяйственныеОперации.СкидкиПодарки)");
    
    РезультатЗапросаПодарки = УправлениеЗапасами.СформироватьЗапросПоТабличнойЧасти(ЭтотОбъект, "Подарки", СтруктураПолейПодарки,СтруктураСложныхПолей, СписокУсловийПодарки);
    
    ТаблицаПодарки          = РезультатЗапросаПодарки.Выгрузить();

    ПроверитьЗаполнениеТабличнойЧастиПодарки(ТаблицаПодарки, СтруктураШапкиДокумента, Отказ, Заголовок);
    
    УправлениеЗапасами.ПроверитьЗаполнениеТабличнойЧастиСерийныеНомера(ЭтотОбъект, "Товары", "СерийныеНомера", Отказ, Заголовок);
    
    //Погашение сертификатами
    ТаблицаПогашения = ПодготовитьТаблицуПогашения();
    
    ПроверитьЗаполнениеТабличнойЧастиПогашения(ТаблицаПогашения, СтруктураШапкиДокумента, Отказ, Заголовок);
    
    
    Если СтруктураШапкиДокумента.ВидОперации = Перечисления.ВидыОперацийЧекККМ.Продажа Тогда
        ТаблицаПоТоварамБезУслугБезКомплектовПодарки = ТаблицаПоТоварамБезУслугБезКомплектов.Скопировать();
        
        ОбщегоНазначения.ЗагрузитьВТаблицуЗначений(ТаблицаПодарки, ТаблицаПоТоварамБезУслугБезКомплектовПодарки);
        
        ПроверитьОстаткиТоваров(СтруктураШапкиДокумента.Дата, РежимПроведения, ТаблицаПоТоварамБезУслугБезКомплектовПодарки, ТаблицаПоКомплектам, Отказ, Заголовок, Результат);
        
        УправлениеЗапасами.ПроверитьДвиженияСерийныхНомеров(ЭтотОбъект, "Товары", "СерийныеНомера", РежимПроведения, Отказ, Заголовок);
        
        УправлениеЗапасами.ПроверитьДвиженияСерийныхНомеровДляПогашения(ЭтотОбъект, РежимПроведения, Отказ, Заголовок);
    Иначе
        
        Если РежимПроведения = РежимПроведенияДокумента.Оперативный Тогда
            ПроверитьВозможностьПроведенияЧекаВозврата(ТаблицаПоТоварам, ТаблицаПоОплате, СтруктураШапкиДокумента, Отказ, Результат);
        КонецЕсли;
        
    КонецЕсли;
    
    Если Отказ Тогда
        ОбщегоНазначения.СообщитьОбОшибке(Результат,,Заголовок);
    Иначе
        
        Если НЕ (КассаККМ.ТипКассы = Перечисления.ТипыКасс.КассаЦентральногоОфиса
             ИЛИ СтатусЧекаККМ = Перечисления.СтатусыЧековККМ.Архивный) Тогда
            
            ТаблицаСерийныхНомеров = УправлениеЗапасами.СформироватьТаблицуСерийныхНомеров(ЭтотОбъект, "Товары", "СерийныеНомера", Истина);
            
            ТаблицаПогашения.Свернуть("ПодарочныйСертификат, СерийныйНомер, Получатель, ХозяйственнаяОперация", "Количество");
            
            ДвиженияПоРегистрам(РежимПроведения, СтруктураШапкиДокумента, ТаблицаПоТоварам, ТаблицаПоКомплектам, ТаблицаПоТоварамБезУслугБезКомплектов, 
                                ТаблицаПоОплате, ТаблицаПодарки, ТаблицаСерийныхНомеров, ТаблицаПогашения, Отказ, Заголовок);
            
        КонецЕсли;
        
    КонецЕсли;


    //m000 Найдем документ движения и проведем его
    Если НЕ Отказ И ВидОперации = Перечисления.ВидыОперацийЧекККМ.Возврат Тогда 
        АСсылкаНаДвижение = Неопределено;
        ЗаписатьДанныеПоДокументуВозврат(Товары, ЭтотОбъект.ЧекККМПродажа, АСсылкаНаДвижение);
        
        ДокументСкидки = m000Сервер.НайтиДокументДвижения( ЭтотОбъект.Ссылка );
        Если ДокументСкидки <> Неопределено Тогда
            Если НЕ ДокументСкидки.Проведен Тогда
                ДокументСкидки.ПолучитьОбъект().Записать(РежимЗаписиДокумента.Проведение);      
            КонецЕсли;  
        КонецЕсли;
        
    КонецЕсли;
    
    Если НЕ Отказ И ВидОперации = Перечисления.ВидыОперацийЧекККМ.Продажа Тогда 
        ДокументСкидки = m000Сервер.НайтиДокументДвижения( ЭтотОбъект.Ссылка );
        Если ДокументСкидки <> Неопределено Тогда
            Если НЕ ДокументСкидки.Проведен Тогда
                ДокументСкидки.ПолучитьОбъект().Записать(РежимЗаписиДокумента.Проведение);      
            КонецЕсли;  
        КонецЕсли;
    КонецЕсли;
    
    
    
    
    //m000/
    

КонецПроцедуры

// Процедура - обработчик события "ПриКопировании".
//
Процедура ПриКопировании(ОбъектКопирования)
    
    СтатусЧекаККМ           = Перечисления.СтатусыЧековККМ.ПустаяСсылка();
    ОтчетОРозничныхПродажах = Документы.ОтчетОРозничныхПродажах.ПустаяСсылка();
    
    НомерСменыККМ = 0;
    НомерЧекаККМ  = 0;
    
    Скидки.Очистить();
    Подарки.Очистить();

    ДисконтнаяКарта = Справочники.ИнформационныеКарты.ПустаяСсылка();
    ВладелецДисконтнойКарты =Неопределено;

КонецПроцедуры

Процедура ОбработкаУдаленияПроведения(Отказ)
    //m000 Найдем документ движения и проведем его
    Если НЕ Отказ Тогда 
        ДокументСкидки = m000Сервер.НайтиДокументДвижения( ЭтотОбъект.Ссылка );
        Если ДокументСкидки <> Неопределено Тогда
            ДокументСкидки.ПолучитьОбъект().Записать(РежимЗаписиДокумента.Проведение);      
        КонецЕсли;
    КонецЕсли;
    //m000/
КонецПроцедуры


////////////////////////////////////////////////////////////////////////////////
// ОПЕРАТОРЫ ОСНОВНОЙ ПРОГРАММЫ

РежимРМК = Ложь;

КонтролироватьОстаткиТоваровПриЗакрытииЧека = Ложь;