Имя: Пароль:
1C
1C 7.7
v7: ККМ чтоб продавать товар с НДС и Без НДС с одной кассы
0 sanekdark
 
27.09.18
12:25
кто может дать совет и где добавить обработку чтоб он товар  или по группе  товаров продавал с ндс. например если группа товаров "Моторные Масла" значит она продает с этой группы с НДС 18% к примеру если не с этой группы то по ЕНВД . кто может подсказать
//******************************************************************************
// ПечатьЧека()
//
// Параметры:
//    Нет
//
// Возвращаемое значение:
//  Нет
//
// Описание:
//    Печатает чек на фискальном регистраторе
//
Процедура ПробитьЧекККМ()    
    
    Перем НомерЧека;
    
    Если Получено < Итог("Сумма") Тогда
        Предупреждение("Не хватает средств для оплаты!");
        Возврат;
    КонецЕсли;
    
    Если НомерЧекаККМ <> 0 Тогда
        Предупреждение("Чек уже пробит на фискальном регистраторе!",60);
        Возврат;
    ИначеЕсли глФРВкл=0 Тогда
        Предупреждение("Фискальный регистратор не подключен!",60);
        Возврат;
    ИначеЕсли ПометкаУдаления()=1 Тогда
        Предупреждение("Документ помечен на удаление, поэтому" + РазделительСтрок +
        "нельзя пробить чек на фискальном регистраторе!",60);
        Возврат;
    ИначеЕсли Проведен()=0 Тогда
        Если Вопрос("Провести документ и пробить чек на фискальном регистраторе?","Да+Нет")="Нет" Тогда
            Возврат;
        КонецЕсли;
        Попытка
            Записать();
            Провести();
        Исключение
            Возврат;
        КонецПопытки;
    ИначеЕсли Модифицированность()=1 Тогда
        Если Вопрос("Сохранить документ и пробить чек на фискальном регистраторе?","Да+Нет")="Нет" Тогда
            Возврат;
        КонецЕсли;
        Попытка
            Записать();
        Исключение
            Возврат;
        КонецПопытки;
    КонецЕсли;
    
    ЗначениеНДС = 6; //БЕЗ НДС
    ПУП = 8; //ЕНВД
    
    СписокТоваров = СоздатьОбъект("ТаблицаЗначений");
    СписокТоваров.НоваяКолонка("ТовНаим"   , "Строка");
    СписокТоваров.НоваяКолонка("Цена"      , "Число");
    СписокТоваров.НоваяКолонка("Количество", "Число");
    СписокТоваров.НоваяКолонка("Сумма"       , "Число");
    СписокТоваров.НоваяКолонка("СтавкаНДС" , "Число");
    
    ВыбратьСтроки();
    Пока ПолучитьСтроку() = 1 Цикл
        СписокТоваров.НоваяСтрока();
        СписокТоваров.ТовНаим    = Сред(СокрЛП(Товар.Код)+"/"+ СокрЛП(Товар.Наименование),1,65);
        СписокТоваров.Цена       = Цена;
        СписокТоваров.Количество = Количество;
        СписокТоваров.Сумма         = Сумма;
    КонецЦикла;
    
    ПризнВозврата = ?(ВидОперации = Перечисление.ВидыОперацийЧекККМ.Чек, 1, 2);
    
    ПроцентСкидки     = ?(Число(ДисконтнаяКарта.Тип.Процент)=0,0,Число(ДисконтнаяКарта.Тип.Процент));
    
    Кассир = "";
    СпрККМ=СоздатьОбъект("Справочник.ККМ");
    Если СпрККМ.НайтиПоРеквизиту("Компьютер", Компьютер.ТекущийЭлемент(),1) = 1 Тогда
        ПУП = глОпределитьПУП(СпрККМ.ПУП);
        ЗначениеНДС = глОпределитьНДС(СпрККМ.СтавкаНДС);
        Если ПустоеЗначение(СпрККМ.КассирККМ.Получить(ДатаДок)) = 0 Тогда
            ВыбКассир = СпрККМ.КассирККМ.Получить(ДатаДок);
            Кассир = глФамилияИмяОтчество(ВыбКассир.Наименование);
        КонецЕсли;
    Иначе
        Предупреждение("Не определены параметры учетной политики, чек не пробит!",60);
        Возврат;
    КонецЕсли;
    
    ТелПокупателя = "";
    ЭлПочтаПокупателя = "";
    
    Если СтрДлина(СокрЛП(КонтактПокупателя))>0 Тогда
        
        Если Найти(КонтактПокупателя,"@") = 0 Тогда //телефон
            ТелПокупателя = СокрЛП(КонтактПокупателя);    
        Иначе //почта
            ЭлПочтаПокупателя = СокрЛП(КонтактПокупателя);
        КонецЕсли;
        
    КонецЕсли;
    
    //ТипОплаты = ?(ВариантОплаты = Перечисление.ТипыОплатЧекаККМ.Наличные,0,1); //наличка - 0, карта - 1
    
    ТипОплаты = 0; //наличка - 0, карта - 1
    
    Если ВариантОплаты = Перечисление.ТипыОплатЧекаККМ.ПлатежнаяКарта Тогда
        ТипОплаты = 1;
    КонецЕсли;
    
    ЧекПробитККМ  = глФРПечататьЧек(СписокТоваров, Итог("Сумма"), ?(Получено=0,Итог("Сумма"),Получено), процентСкидки, ПризнВозврата, ЗначениеНДС, НомерЧека, ПУП, Кассир, ТелПокупателя, ЭлПочтаПокупателя, ТипОплаты);
    Если ЧекПробитККМ = 1 Тогда
        НомерЧекаККМ  = ?(НомерЧека = 0, -1, НомерЧека);
        СтатусЧекаККМ = Перечисление.СтатусыЧековККМ.Пробитый;
        ПриЗаписиПерепроводить(0);
        Записать();
        ПриЗаписиПерепроводить(1);
    КонецЕсли;
    
КонецПроцедуры  


вот код печати чека а еще один смотреть над в frATOL54_comm.ert тут правельно я думаю?
1 s03
 
27.09.18
12:30
думаешь почти правЕльно, посмотри глобальную процедуру глФРПечататьЧек сначала, может до внешней обработки и не понадобится добираться
2 sanekdark
 
27.09.18
12:47
//******************************************************************************
//  глОпределитьПУП(знПУП)
//
// Параметры:
//    знПУП        - текущая ПУП.
//
// Возвращаемое значение:
//  Отформатированная строка
//
// //0 - Общая СНО, 1 - УСН Доход, 2 - УСН Доходы-Расходы, 3 - ЕНВД, 4 - ЕСХН, 5 - ПСН



Функция глОпределитьПУП(знПУП) Экспорт

        Если знПУП = Перечисление.ПУП.ОСН Тогда
            Возврат 1;
        ИначеЕсли знПУП = Перечисление.ПУП.УСНДоход Тогда
            Возврат 2;
        ИначеЕсли знПУП = Перечисление.ПУП.УСНДоходыРасходы Тогда  
            Возврат 4;
        ИначеЕсли знПУП = Перечисление.ПУП.ЕНВД Тогда
            Возврат 8;
        Иначе
            Возврат -1;
        КонецЕсли;

КонецФункции // глОпределитьПУП()  

//******************************************************************************
//  глОпределитьНДС(ЗначениеНДС)
//
// Параметры:
//
// Возвращаемое значение:
//  Отформатированная строка
//



Функция глОпределитьНДС(ЗначениеНДС) Экспорт

        Если ЗначениеНДС = Перечисление.ЗначенияНДС.ОсновнаяСтавкаНДС Тогда
            Возврат 1;
        ИначеЕсли ЗначениеНДС = Перечисление.ЗначенияНДС.ЛьготнаяСтавкаНДС Тогда
            Возврат 2;
        ИначеЕсли ЗначениеНДС = Перечисление.ЗначенияНДС.безНДС Тогда  
            Возврат 6;
        КонецЕсли;

КонецФункции // глОпределитьНДС()  

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

        Параметры.Установить("ПУП"                      , ПУП);
        Параметры.Установить("Кассир"                  , Кассир);
        
        Параметры.Установить("ПриемНаличныхОтЮрЛиц"    , глФРДляПриемаНаличныхОтЮрЛиц);
        
        Параметры.Установить("ТелПокупателя"           , ТелПокупателя);  
        Параметры.Установить("ЭлПочтаПокупателя"       , ЭлПочтаПокупателя);
        
        Параметры.Установить("ТипОплаты"               , ТипОплаты);  

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



вот с глобального код не совсем понимаю что делать можете подсказать
3 Kigo_Kigo
 
27.09.18
12:55
Даю наводку, ставка ндс привязана к каждой позиции номенклатуры, с вас на водку :)
4 sanekdark
 
27.09.18
13:02
//Мое добавление
Ном = СоздатьОбъект("Справочник.Товары");
Ном.ВыбратьЭлементы() ;
Если Ном.СтавкаНДС=18 тогда
    ЗначениеНДС = 1; //БЕЗ НДС
    ПУП = 1; //ЕНВД
              //конец
     Иначе
    ЗначениеНДС = 6; //БЕЗ НДС
    ПУП = 8; //ЕНВД
    
    СписокТоваров = СоздатьОбъект("ТаблицаЗначений");
    СписокТоваров.НоваяКолонка("ТовНаим"   , "Строка");
    СписокТоваров.НоваяКолонка("Цена"      , "Число");
    СписокТоваров.НоваяКолонка("Количество", "Число");
    СписокТоваров.НоваяКолонка("Сумма"       , "Число");
    СписокТоваров.НоваяКолонка("СтавкаНДС" , "Число");
    

так правильно?
5 sanekdark
 
27.09.18
13:13
ребят я ток вникаю учусь в 1с 7.7 еще плохо понимаю что как строго не судите изучаю сам с помощью итнернета гдето понимаю гдето не со всем
6 Kigo_Kigo
 
27.09.18
13:22
нет, ставка ндс это перечисление

   СписокТоваров = СоздатьОбъект("ТаблицаЗначений");
    СписокТоваров.НоваяКолонка("ТовНаим"   , "Строка");
    СписокТоваров.НоваяКолонка("Цена"      , "Число");
    СписокТоваров.НоваяКолонка("Количество", "Число");
    СписокТоваров.НоваяКолонка("Сумма"       , "Число");
    СписокТоваров.НоваяКолонка("СтавкаНДС" , "Число");
    
    ВыбратьСтроки();
    Пока ПолучитьСтроку() = 1 Цикл
        СписокТоваров.НоваяСтрока();
        СписокТоваров.ТовНаим    = Сред(СокрЛП(Товар.Код)+"/"+ СокрЛП(Товар.Наименование),1,65);
        СписокТоваров.Цена       = Цена;
        СписокТоваров.Количество = Количество;
        СписокТоваров.Сумма         = Сумма;
Если ТОвар.СтавкаНдс = Перечисление.СтавкиНДС.НДС18 Тогда
СписокТоваров.СтавкаНдс  = 18;
КонецЕсли;

    КонецЦикла;
7 Kigo_Kigo
 
27.09.18
13:27
А точнее так
        Если Номенклатура.СтавкаНДС = Перечисление.СтавкиНДС.БезНДС Тогда
            СписокТоваров.СтавкаНДС  = "none";
        Иначе    
            СписокТоваров.СтавкаНДС  = 100 * глНачисляемыйНДС(Номенклатура.СтавкаНДС);
        КонецЕсли;
8 sanekdark
 
27.09.18
15:07
у меня нет глНачисляемыйНДС
подругому могу сделать  же так  на пример
Если Товар.СтавкаНДС = Перечисление.СтавкиНДС.БезНДС Тогда
            СписокТоваров.СтавкаНДС  = "none";
        Иначе    
            СписокТоваров.СтавкаНДС  = 18;
        КонецЕсли;
9 sanekdark
 
27.09.18
15:08
у меня самописная конфигурация не типовая. досталось от старого программиста
10 Aleksey
 
27.09.18
15:17
Нельзя в одном чеке пробивать 2 режима налогооблажения (масло + ЕНВД)
СНО это реквизит шапки, а не товара
11 Kigo_Kigo
 
27.09.18
15:32
(10) да забыл добавить что чек надо дробить на 2, если присутствую товары и усн и енвд, и выбивать 2 чека
12 sanekdark
 
27.09.18
16:37
а как его раздробить? подскажите
13 Kigo_Kigo
 
27.09.18
17:55
(12) Ну кпримеру 2 раза проходить процедуру Пробить чек ККМ, первый раз в СписокТоваров добавлять товары УСН и отправлять - на пробитие, второй только енвд
14 sanekdark
 
27.09.18
18:11
я же в принципе могу просто чек сделать отдельный именно под масла  один будет товарный чек под енвд а другой под ОСН просто прописать там тоже самое ток поменять налого обложение)))  так же тоже можно?
15 sanekdark
 
27.09.18
18:11
просто не понимаю как сделать две процедуры (
16 Гад
 
27.09.18
18:14
масла на отдельный склад перемести да и все
17 Гад
 
27.09.18
18:14
и в чек реквизит выведи
18 sanekdark
 
27.09.18
18:27
у меня не типовая конфа а по отдельному складу как? реализовать?
19 Гад
 
27.09.18
18:38
если склад.номерсеции = 1 тогда пуп = ойляля иначе
пуп = лялялой
зы судя по 1с 7 и уровню спеца в сетке магазина 2 -3, перетерпят и отдельными чеками бить, походу проходиомсть маленькая и в чек на форму вывести склад для выбора продавцом (ну мон еще какуюнить шляпу на корректность заполненного чека
табчасть.выгрузить(тз)
тз.свернуть("признакподакциного")
если тз.колвострок() >1 тогда пред-е("ой");
20 Kigo_Kigo
 
27.09.18
18:39
(16) худший вариант, может еще модуль проведения чека ему посоветуете переписать, чтобы по разным складам проводилось?
21 Гад
 
27.09.18
18:44
)чем худший-? тут либо обработку писатьпо формирвоанию двух чеков (по сути фронт со всеми его заморочками) либо малой кровью
22 Kigo_Kigo
 
27.09.18
18:45
Короче вот вам код, адаптируйте под себя
Функция ПробитьЧекНаККМ()
    Перем НомерЧека;
    Если Продавец.Выбран() = 1 Тогда
        Если Продавец.Пароль = 0 Тогда
            Предупреждение("У Продавца не введен пароль");
            Возврат 0;
        КонецЕсли;
    Иначе
        Предупреждение("Не выбран продавец");
        Возврат 0;
    КонецЕсли;
    
    Пароль = Продавец.Пароль;
    ПризнВозврата = ?(ВидОперации = Перечисление.ВидыОперацийЧекККМ.Чек, 0, 1);
    
    СписокТоваров1 = СоздатьОбъект("ТаблицаЗначений");
    СписокТоваров1.НоваяКолонка("Товар"   , "Справочник.Номенклатура");
    СписокТоваров1.НоваяКолонка("Цена"      , "Число");
    СписокТоваров1.НоваяКолонка("Количество", "Число");
    СписокТоваров1.НоваяКолонка("Сумма"       , "Число");
    СписокТоваров1.НоваяКолонка("СтавкаНДС" , "Строка");
    СписокТоваров1.НоваяКолонка("СуммаСкидки" , "Число");

    ВыбратьСтроки();
    Пока ПолучитьСтроку() = 1 Цикл
        СписокТоваров1.НоваяСтрока();
        СписокТоваров1.Товар    = Номенклатура;
        СписокТоваров1.Цена       = Цена;
        СписокТоваров1.Количество = Количество;
        СписокТоваров1.Сумма         = Сумма;
        СписокТоваров1.СтавкаНДС  = "none";
        СписокТоваров1.СуммаСкидки  = СуммаСкидки;

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

        Иначе    
            СписокТоваров.СтавкаНДС  = 100 * глНачисляемыйНДС(Номенклатура.СтавкаНДС);
        КонецЕсли;
    КонецЦикла;
    
    ПризнВозврата = ?(ВидОперации = Перечисление.ВидыОперацийЧекККМ.Чек, 0, 1);
    СуммаЧека = СписокТоваров.Итог("Сумма");
    Получено1 = СписокТоваров.Итог("Сумма");
    //ПУП = 1; // Допустимые значения: 0 - Общая СНО, 1 - УСН Доход, 2 - УСН Доходы-Расходы, 3 - ЕНВД, 4 - ЕСХН, 5 - ПСН
    НомерСекции = 1;
    Если НомерЧека = "" Тогда
        НомерЧека = "";
    КонецЕсли;
    ТипНалогов = 4;
    Если СписокТоваров.КоличествоСтрок() > 0 Тогда
        ЧекПробитККМ  = глФРПечататьЧек(СписокТоваров,Пароль, Итог("Сумма"), ?(Получено=0,Итог("Сумма"),Получено), ПолучитьПустоеЗначение("Справочник.Скидки"), ПризнВозврата, Секция, НомерЧека,ТипНалогов,СписокТоваров.Итог("СуммаСкидки"),ВидОплаты,КудаОтправитьЧек);        
    КонецЕсли;
    Вопрос("Подождите идет пробитие чеков",0,5);
    
    
    СписокТоваров = СоздатьОбъект("ТаблицаЗначений");
    СписокТоваров.НоваяКолонка("ТовНаим"   , "Строка");
    СписокТоваров.НоваяКолонка("Цена"      , "Число");
    СписокТоваров.НоваяКолонка("Количество", "Число");
    СписокТоваров.НоваяКолонка("Сумма"       , "Число");
    СписокТоваров.НоваяКолонка("СтавкаНДС" , "Строка");
    СписокТоваров.НоваяКолонка("СуммаСкидки" , "Число");


    СписокТоваров1.ВыбратьСтроки();
    Пока СписокТоваров1.ПолучитьСтроку() = 1 Цикл
        Если СписокТоваров1.Товар.ТоварУСН = 1 Тогда
            Продолжить;
        КонецЕсли;
        СписокТоваров.НоваяСтрока();
        СписокТоваров.ТовНаим    = СписокТоваров1.Товар.Наименование;
        СписокТоваров.Цена       = СписокТоваров1.Цена;
        СписокТоваров.Количество = СписокТоваров1.Количество;
        СписокТоваров.Сумма         = СписокТоваров1.Сумма;
        Если Номенклатура.СтавкаНДС = Перечисление.СтавкиНДС.БезНДС Тогда
        СписокТоваров.СтавкаНДС  = "none";
        Иначе    
            СписокТоваров.СтавкаНДС  = 100 * глНачисляемыйНДС(Номенклатура.СтавкаНДС);
        КонецЕсли;
    КонецЦикла;
    
    СуммаЧека = СписокТоваров.Итог("Сумма");
    Получено1 = СписокТоваров.Итог("Сумма");
    //Скидка = Скидка;
    //ПризнВозврата = 0;
    //ПУП = 1; // Допустимые значения: 0 - Общая СНО, 1 - УСН Доход, 2 - УСН Доходы-Расходы, 3 - ЕНВД, 4 - ЕСХН, 5 - ПСН
    НомерСекции = 1;
    Если НомерЧека = "" Тогда
        НомерЧека = "";
    КонецЕсли;
    ДлинаСтроки = 48;
    ТипНалогов = 8;
    //ПечататьЧек(Объект, Пароль, СписокТоваров, Получено, Скидка, ПризнВозврата, НомерСекции, НомерЧека,ТипНалогов)
    Если СписокТоваров.КоличествоСтрок() > 0 Тогда
        ЧекПробитККМ  = глФРПечататьЧек(СписокТоваров,Пароль, Итог("Сумма"), ?(Получено=0,Итог("Сумма"),Получено), ПолучитьПустоеЗначение("Справочник.Скидки"), ПризнВозврата, Секция, НомерЧека,ТипНалогов,СписокТоваров.Итог("СуммаСкидки"),ВидОплаты,КудаОтправитьЧек);        
    КонецЕсли;
    
    ///******************************************************************************************************
    
    
    
    
    
    
    
    
    
    
    
    
    
    Если ЧекПробитККМ = 1 Тогда
        ПриЗаписиПерепроводить(0);
        НомерЧекаККМ = НомерЧека;
        Записать();
        ПриЗаписиПерепроводить(1);
        
        // Откроем денежный ящик, если он подключен
        глДПОткрытьДенежныйЯщик();
    КонецЕсли;
    
    Возврат ЧекПробитККМ;
    
КонецФункции // ПробитьЧекНаККМ()
23 Гад
 
27.09.18
18:45
+21 к 20 и да сеня, вы дэбил)
24 Kigo_Kigo
 
27.09.18
18:47
В Справочник номенклатура добавить реквизит ТоварУсн тип число, вывести на форму как галка, в товарах усн проставить эту галку
25 Kigo_Kigo
 
27.09.18
18:47
(23) обоснуй
26 Гад
 
27.09.18
18:49
(22) шедеврально), обоснуют тебе на зоне
27 sanekdark
 
27.09.18
18:56
Kigo_Kigo спасибо завтра пробывать буду с утра спасибо  завтра отпишусь
28 Гад
 
27.09.18
19:11
надо больше золота ..ой циклов
Проблемы невозможно решaть нa том же уровне компетентности, нa котором они возникaют. Альберт Эйнштейн