gifts2017

"Недовоз" - что может быть проще...

Опубликовал Иван (Ioann) в раздел Программирование - Практика программирования

Разработка документа "Акт недовоза" в комплексной конфигурации ред. 4.3
Возникла у меня как-то задача автоматизировать недовоз. Что это за зверь такой? Обычная схема отгрузки, поставки товара: выписываем отгрузочные документы, подготовленный заказ грузим в автомобиль, везем. В процессе разгрузки, приёмки оказывается, что не все соответствует документам – что-то, куда-то утряслось, усохло или наоборот подросло и переродилось. От каких-то товаров клиент отказался по причине брака, нетоварного вида, отсутствующей сопроводительной документации и т.д. В результате имеем новый вариант отгрузочных документов. Казалось бы, что тут автоматизировать, в смысле автоматизировать вообще ничего не надо…
Рассмотрим, как отразить такую ситуацию в типовой торговле ред. 9 на 7-ке или комплексной с тем же функционалом оперативного учета. У нас используется конфигурация на базе комплексной ред. 4.3 – сильно доработанная, но общая схема заявок, отгрузок соответствует типовой. В самом простом случае в системе введен документ «Реализация (купля-продажа)», отражающий факт отгрузки со склада. В более сложном случае реализация введена на основании заявки, по которой формировался резерв (нескольких заявок: неподтвержденной, заявки на склад). Итак, получаем результат доставки товара до клиента – документ, в котором зафиксированы расхождения. Правим документ отгрузки, чтобы получить нужную картину, проводим. В случае добавления новых строк, увеличения количества чего-то, могут возникнуть проблемы с наличием этого на складе, с последовательностью документов. В случае уменьшения количества, удаления строк проблем с проведением документа не должно быть, но при этом получаем следующее: удаленный товар появился на складе и остался в резерве. Значит необходимо ввести документ «Перемещение ТМЦ» на склад ошибок до разбирательства (ведь товара то может и не быть физически на нашем складе) и документ «Снятие резерва», в случае, если был резерв. Поместить эти документы сразу после реализации, причем сначала «Снятие резерва», потом «Перемещение». А вот это уже задача для оператора не простая, если его еще отвлекают чем-то. Необходимо создать два документа, исправить реализацию, да еще не перепутать время, да еще резерв мог быть, а могло не быть… Помимо ошибок склада, отдела отгрузок еще и баги с последовательностью документов вылезут. Хорошо, если таких недовозов один в неделю, тогда понятно можно потерпеть и попотеть, а если несколько в день – уже напрягает и не только оператора, но и других тоже, кто потом ошибки вылавливает. В общем задача автоматизации налицо, задача именно по недовозу, поскольку перевозы и замена решаются проще, а вот исчезновение товара сложнее.
Сначала я решил, что написать один документик, который формирует два других - задача несложная и её можно поручить кому-то. У самого времени не хватает, других задач выше крыши и т.д. А потом решил, что задача совсем несложная – дольше будешь её описывать, тестировать, короче издержки на взаимодействие больше, чем взять и написать самому. Подумав, немножко сформулировал для себя задачу: «Создать документ «Акт недовоза», вводимый на основании реализации. В шапке документа указывается склад недовоза. В табличной части документа указывается исправляемая номенклатура, недовезенное количество. При проведении документ исправляет документ отгрузки (Реализация), формирует два документа «Снятие резерва», «Перемещение ТМЦ» (далее буду называть их подчиненными документами), помещает их в нужной последовательности сразу после документа отгрузки». Пораскинув еще немного мозгами, добавил требования:
1. После проведения «Акта недовоза» документ отгрузки блокируется от изменений, изменения могут быть проведены только после отмены проведения «Акта недовоза».
2. При отмене проведения «Акта недовоза» документ отгрузки исправляется обратно, т.е возвращается в исходное состояние. Подчиненные документы («Снятие резерва», «Перемещение ТМЦ") снимаются с проведения.
3. При пометке на удаление «Акта недовоза» подчиненные документы тоже помечаются на удаление.
4. Из пункта 1 и 2 следует, что больше одного «Акта недовоза» на основании одного документа отгрузки быть не может. (Хотя из логики самого документа это тоже следует).

Осознав все это, я первый раз подумал, что задача не такая простая, как кажется, и бодро взялся за дело.
Структура документа и форма документа ничего особо ценного из себя не представляют, но на парочке моментах я остановлюсь. Из задачи вытекает, что минимально документ должен иметь реквизиты шапки «ДокОснование», «СкладНедовоза» и реквизиты табличной части «Номенклатура», «Количество», «Единица», «Коэффициент». Я добавил еще реквизиты шапки «Контрагент» - для отбора документа по графе «Контрагент» и «Сумма» - для отображения суммы недовоза в журналах. Основной вопрос: «как определить сумму недовоза?». Нехорошо держать в самом документе цены, суммы, да и вариант расчета налогов – вся эта информация относится к документу отгрузки. Для подсчета суммы недовоза в модуле формы завел переменную «ЭкземплярДокОснования» - объект вида документа отгрузки. Эта переменная принимает ссылку на значение документа-основания, таким образом полностью соответствует документу отгрузки. В этом экземпляре количество для нормальных позиций (довезенных) принимает нулевое значение, для остальных количество, указанное в недовозе. В результате, используя типовую процедуру глПересчетТаблЧасти(ЭкземплярДокОснования, "Количество"), получаем итог по недовозу. В экранной форме документа у меня отображается сумма документа отгрузки и сумма недовоза – эти значения получаются одной и той же функцией с различными параметрами ПолучитьИтог().

 
Функция ПолучитьИтог(ВидИтога, Док = 0, ТипИтога = "строка")
    
    Рез = 0;
    Если ДокОснование.Выбран() > 0 Тогда
        Если ВидИтога = "Всего" Тогда
            Если Док = 0 Тогда
                Рез = ДокОснование.Итог("Сумма") +
                    ?(ДокОснование.СуммаВклНП=1, 0, ДокОснование.Итог("СуммаНП")) +
                    ?(ДокОснование.СуммаВклНДС=1, 0, ДокОснование.Итог("СуммаНДС"));        
            Иначе
                Рез = ЭкземплярДокОснования.Итог("Сумма") +
                    ?(ЭкземплярДокОснования.СуммаВклНП=1, 0, ЭкземплярДокОснования.Итог("СуммаНП")) +
                    ?(ЭкземплярДокОснования.СуммаВклНДС=1, 0, ЭкземплярДокОснования.Итог("СуммаНДС"));                            
            КонецЕсли;
        ИначеЕсли ВидИтога = "НДС" Тогда
            Если Док = 0 Тогда
                Рез = ДокОснование.Итог("СуммаНДС");    
            Иначе
                Рез = ЭкземплярДокОснования.Итог("СуммаНДС");
            КонецЕсли;
        ИначеЕсли ВидИтога = "НП" Тогда
            Если Док = 0 Тогда
                Рез = ДокОснование.Итог("СуммаНП");                
            Иначе
                Рез = ЭкземплярДокОснования.Итог("СуммаНП");
            КонецЕсли;
        КонецЕсли;        
    КонецЕсли;
    Если ТипИтога = "строка" Тогда
        Возврат глФРМ(Рез);
    Иначе
        Возврат Рез;
    КонецЕсли;
КонецФункции // ПолучитьИтог() 

Понятно, что пересчет документа «ЭкземплярДокОснования» производится при изменении количества, удалении, добавлении строк акта недовоза. При записи акта сохраняется реквизит «Сумма»: Сумма = ПолучитьИтог("Всего", 1, "число"). Таким образом удалось избежать ненужного дублирования информации о суммах, налогах в акте недовоза. Не сразу до меня доперло, а только уже на очередном этапе тестирования, что номенклатура, недовезенная полностью, удаляется из документа-основания (отгрузки) полностью… и для сохраненного акта недовоза сумма недовоза рассчитывается без учета этих позиций, да и при отмене проведения акта нужно вернуть эти позиции в отгрузку, а по каким ценам? Поэтому в табличную часть акта недовоза пришлось добавить реквизиты «Цена», «СтавкаНДС», «СтавкаНП» - ставки уж так до кучи, так проще получается – вдруг их кто-то вздумает менять. Итак, процедура ПересчетЭкземпляраДокОснования() выглядит следующим образом:

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



В модуль документа вынес основные задачи, решаемые документом. Сам документ движений никаких не формирует, но формирует и проводит новые документы, исправляет документ отгрузки. Стандартно в 1С нельзя проводить документы из процедудры ОбработкаПроведения(), но эта проблема решается с помощью трюка, описанного неоднократно в разных местах. Я на это наткнулся где-то в клубе http://1c.proclub.ru. - вариант использования обработки. Документ для проведения передается в обработку, в процедуре ПриОткрытии() производится закрытие Форма.Закрыть(0), а в процедуре ПриЗакрытии() проведение переданного документа. Не знаю, кто автор этой идеи, но красиво. Первый раз, когда использовал эту идею, сразу подумал, что надо сделать небольшую универсальную обработку «ПроведениеИзМодуляПроведения». Вот тут без неё точно никуда, поскольку надо не один документ проводить из модуля другого, а целых три, да еще отменить все это дело на любом этапе возникновения ошибки. Обработка выложена в программах, как иллюстрация к данной статье. Там и описание есть небольшое, как ей пользоваться.
Итак модуль проведения акта недовоза содержит следующее:
1. Изменение документа-основания (отгрузка)
2. Определение времени новых создаваемых документов. Так, чтобы они легли сразу после отгрузки до следующих документов.
3. Создание документов «Снятие резерва», «Перемещение ТМЦ».

Текст модуля документа приведен в конце статьи, процедура ОбработкаПроведения() не целиком – исключил изменения документа-основания, ОбработкаУдаленияПроведения() – целиком. Документ «Снятие резерва» создается только в случае наличия резерва по изменяемым позициям отгрузки. Сначала я сделал вариант какой-то … не помню уже конкретно, вроде, наличие резерва по списку недовезенных позиций на момент отгрузки, т.е. временный расчет регистра – по логике так, но на очередном этапе тестирования сообразил… Проще взять движения документа отгрузки по резервам, изменить документ отгрузки, получить разницу, и по ней уже снимать резерв. Как обычно, хорошие мысли приходят уже, когда сделаешь вариант, погоняешь его… а потом сделаешь новый!
Исключить большинство ошибок в процессе тестирования - все одно не удается, поэтому некоторые сводят его до минимума, и все тестирование происходит в процессе, э-э… как это называется «опытной эксплуатации». И в этом случае обнаружились баги, и не только мои. Напомню, что весь этот огород происходил на комплексной конфе, в качестве основы релиз в районе 432. Критичные изменения, исправления ошибок, выдаваемые 1С-ом, я обычно отслеживаю и вношу ручками. Но здесь пропустил, оказалось, что у меня документ «Снятие резерва» не входит в основную последовательность документов. Причем понял я это через пару месяцев, а может и три «опытной эксплуатации». Восстановление последовательности стало постоянно затыкаться на заявках, в основном на резервах – и раньше такое было (оно и понятно). Обычно делались служебные документы снятия резерва, но после ввода в действие акта недовоза такие моменты пошли особенно часто. Сначала подумал, что чехарда с резервом связана со снятием резерва по договору, поскольку много заявок по одному договору (много получателей, клиент один и договор один). Сделал явное снятие резерва по заявке для документов, создаваемых актом недовоза, но это не помогло, пришлось рыть дальше…
Избежать большинства ошибок, связанных с пользователями, мне помогла продуманная схема блокирования – сделал я практически сразу в конечном виде, до процесса «опытной эксплуатации».
Но для этого пришлось «затычки» ставить во многих местах конфигурации:
1. В документы отгрузки, в процедуру ПриОткрытии() проверка наличия подчиненного, проведенного акта недовоза – в случае наличия, только просмотр документа.
2. В документы «Снятие резерва», «Перемещение ТМЦ" в процедуру ПриОткрытии() проверка документа-основания. Для документов, введенных на основании акта недовоза, только просмотр и предупреждение, что все изменения с данным документом могут производиться только через акт недовоза.
3. Закрыл изменение проведенного документа «Акт недовоза» - только просмотр. Для внесения изменений нужно сначала сделать отмену проведения. Надежнее, поскольку при перепроведении не вызывается ОбработкаУдаленияПроведения().
4. В функцию глобального модуля глПриУдаленииДокумента(), вызываемую из предопределенной ПриУдаленииДокумента() добавлено:
- установка / снятие пометки удаления с документов «Снятие резерва», «Перемещение ТМЦ" при установке / снятии пометки удаления «Акта недовоза» с проверкой даты запрета редактирования.
- блокирование установки / снятия пометки удаления с документов «Снятие резерва», «Перемещение ТМЦ», имеющих основание «Акт недовоза»
- блокирование установки пометки удаления документа отгрузки, имеющего подчиненный непомеченный на удаление документ «Акт недовоза»
5. В предопределенную процедуру ПриОтменеПроведенияДокумента() добавлено:
- блокирование отмены проведения документов «Снятие резерва», «Перемещение ТМЦ", имеющих основание «Акт недовоза»
- блокирование отмены проведения документа отгрузки, имеющего подчиненный проведенный документ «Акт недовоза»

6. В общем журнале документов, в форме списка добавил блокирование изменения времени документа по кнопке «Время» для документов «Снятие резерва» и «Перемещение ТМЦ", имеющих основание «Акт недовоза».

В процессе использования еще парочку маленьких удобств для пользователей добавил. В экранной форме акта групповую пометку, удаление отмеченных строк табличной части, кнопку обновления табличной части по документу-основанию.

Вот такой вот нехилый «Недовоз» получился!!! Работает больше года, за 2006 год уже больше 900 документов вида «Акт недовоза»…

Процедура ОбработкаПроведения()

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

    ....

    // запись измененного документа
    Попытка
        Док.Записать();        
        // проведение документа
        КонтФормы = Док.ТекущийДокумент();
        ОткрытьФорму("Обработка.ПроведениеИзМодуляПроведения", КонтФормы);
    Исключение    
        Сообщить("Не удалось изменить документ " + глПредставлениеДокумента(ДокОснование) + " " + ОписаниеОшибки());
        СтатусВозврата(0);
        Возврат;
    КонецПопытки;
    ТаблРеализации = СоздатьОбъект("ТаблицаЗначений");
    Док.ВыгрузитьТабличнуюЧасть(ТаблРеализации, "Номенклатура, Количество, Коэффициент");
        
    
    // определяем времена документов
    Док = СоздатьОбъект("Документ");
    Док.ВыбратьПодчиненныеДокументы( , , ТекущийДокумент());
    Пока Док.ПолучитьДокумент() > 0 Цикл
        Если Док.Вид() = "ПеремещениеТМЦ" Тогда
            Прервать;
        КонецЕсли;
    КонецЦикла;
        ДокПеремещение = СоздатьОбъект("Документ.ПеремещениеТМЦ");
    Если Док.Выбран() > 0 Тогда
        ДокПеремещение.НайтиДокумент(Док.ТекущийДокумент());    
    КонецЕсли;
    
    ВремяДокОснования = глПолучитьВремяДокументаЧислом(ДокОснование);
    ВремяПеремещения = ВремяДокОснования + 10;   // на 10 секунд, если нет других документов        
    Док.ВыбратьДокументы(СформироватьПозициюДокумента(ДокОснование, 1), ДокОснование.ДатаДок);
    Если Док.ПолучитьДокумент() = 1 Тогда
        Если Док.ТекущийДокумент() = ДокПеремещение.ТекущийДокумент() Тогда
            Док.ПолучитьДокумент();
        КонецЕсли;
        Если Док.Выбран() > 0 Тогда
            Время2 = глПолучитьВремяДокументаЧислом(Док);
            Если Время2 <= ВремяПеремещения Тогда
                ВремяПеремещения = Окр((ВремяДокОснования + Время2) / 2);    
            КонецЕсли;        
        КонецЕсли;
    КонецЕсли;
    
    // подготовка таблицы резервов
    ТаблРезервов.ВыбратьСтроки();
    Н = 1;
    Пока Н <= ТаблРезервов.КоличествоСтрок() Цикл
        ТаблРезервов.ПолучитьСтрокуПоНомеру(Н);
            Поз = 0;
        ТаблРеализации.НайтиЗначение(ТаблРезервов.Номенклатура, Поз, "Номенклатура");
        Если Поз > 0 Тогда
            // в базовых единицах
            Поправка = ТаблРеализации.ПолучитьЗначение(Поз, "Количество") *
                        ТаблРеализации.ПолучитьЗначение(Поз, "Коэффициент");
            ТаблРезервов.Количество = ТаблРезервов.Количество - Поправка;
        КонецЕсли;
        Если ТаблРезервов.Количество <= 0 Тогда
            ТаблРезервов.УдалитьСтроку();
        Иначе
            Н = Н + 1;
        КонецЕсли;
    КонецЦикла;
        
    Если ТаблРезервов.КоличествоСтрок() > 0 Тогда
        Док.ВыбратьПодчиненныеДокументы( , , ТекущийДокумент());
        Пока Док.ПолучитьДокумент() > 0 Цикл
            Если Док.Вид() = "СнятиеРезерва" Тогда
                Прервать;    
            КонецЕсли;
        КонецЦикла;
        ДокСнятиеРезерва = СоздатьОбъект("Документ.СнятиеРезерва");
        
        Если (Док.Выбран() > 0) И (Док.Вид() = "СнятиеРезерва") Тогда
            ДокСнятиеРезерва.НайтиДокумент(Док.ТекущийДокумент());
            
        Иначе
            ДокСнятиеРезерва.Новый();     
        КонецЕсли;
        
        ДокСнятиеРезерва.ДокОснование = ТекущийДокумент();
        // 16.03.06 добавлена блокировка
        ДокСнятиеРезерва.Блокировка = 1;
        ДокСнятиеРезерва.ДатаДок = ДокОснование.ДатаДок;
        ДокСнятиеРезерва.АвтоВремяОтключить();
        глУстановитьВремяДокументаЧислом(ДокСнятиеРезерва, Окр((ВремяДокОснования + ВремяПеремещения) / 2));    
        глЗаполнитьШапку(ДокСнятиеРезерва, 0);    
        ДокСнятиеРезерва.ВидОперации = "Снятие резерва по складу";
        ДокСнятиеРезерва.Фирма = ДокОснование.Фирма;
        ДокСнятиеРезерва.ЮрЛицо = ДокОснование.ЮрЛицо;
        ДокСнятиеРезерва.Склад = ДокОснование.Склад;
        ДокСнятиеРезерва.Проект = ДокОснование.Проект;
        ДокСнятиеРезерва.Комментарий = "По акту недовоза №" + СокрЛП(НомерДок) + " от " + ДатаДок;
        
        ДокСнятиеРезерва.УдалитьСтроки();
        ТаблРезервов.ВыбратьСтроки();
        Пока ТаблРезервов.ПолучитьСтроку() > 0 Цикл
            ДокСнятиеРезерва.НоваяСтрока();
            ДокСнятиеРезерва.Договор = ДокОснование.Договор;
            ДокСнятиеРезерва.Контрагент = ДокОснование.Контрагент;
            ДокСнятиеРезерва.Номенклатура = ТаблРезервов.Номенклатура;
            ДокСнятиеРезерва.Количество = ТаблРезервов.Количество;
            ДокСнятиеРезерва.Единица = ТаблРезервов.Номенклатура.БазоваяЕдиница;
            ДокСнятиеРезерва.Коэффициент = 1;
            // !!! по заявке сделал 26.07.05
            ДокСнятиеРезерва.Заявка = ТаблРезервов.Заявка;
        КонецЦикла;
        
        Попытка
            ДокСнятиеРезерва.Записать();
        Исключение
            Сообщить("" + ОписаниеОшибки());
            Если ДокСнятиеРезерва.Выбран() = 0 Тогда
                Сообщить("Документ ""Снятие резерва"" на создан!");    
            КонецЕсли;
            СтатусВозврата(0);
            Возврат;
        КонецПопытки;    
        КонтФормы = ДокСнятиеРезерва.ТекущийДокумент();
        ОткрытьФорму("Обработка.ПроведениеИзМодуляПроведения", КонтФормы);        
    КонецЕсли;
    
    // Создание документа "Перемещение"    
    Если ДокПеремещение.Выбран() = 0 Тогда
        ДокПеремещение.Новый();    
    КонецЕсли;
    
    ДокПеремещение.ДатаДок = ДокОснование.ДатаДок;
    // 16.03.06 добавлена блокировка
    ДокПеремещение.Блокировка = 1;
    ДокПеремещение.АвтоВремяОтключить();
    глУстановитьВремяДокументаЧислом(ДокПеремещение, ВремяПеремещения);
    
    глЗаполнитьШапку(ДокПеремещение, 0);    
    ДокПеремещение.ДокОснование = ТекущийДокумент();
    глЗаполнитьШапкуНаОсн(ДокПеремещение, ТекущийДокумент());
    ДокПеремещение.Склад = ДокОснование.Склад;
    ДокПеремещение.ФирмаПолучатель = Фирма;
    ДокПеремещение.СкладПолучатель = СкладНедовоза;
    ДокПеремещение.Комментарий = глПредставлениеДокумента(ТекущийДокумент()) + " к док-ту " + глПредставлениеДокумента(ДокОснование);
    ДокПеремещение.УдалитьСтроки();
    ВыбратьСтроки();
    Пока ПолучитьСтроку() > 0 Цикл
        ДокПеремещение.НоваяСтрока();
        ДокПеремещение.Номенклатура = Номенклатура;
        ДокПеремещение.Количество = Количество;
        ДокПеремещение.Единица = Единица;
        ДокПеремещение.Коэффициент = Коэффициент;
    КонецЦикла;
    Попытка
        ДокПеремещение.Записать();
        КонтФормы = ДокПеремещение.ТекущийДокумент();
        ОткрытьФорму("Обработка.ПроведениеИзМодуляПроведения", КонтФормы);
    Исключение
        Сообщить(ОписаниеОшибки());
        Сообщить("Не удалось изменить документ " + глПредставлениеДокумента(ДокПеремещение.ТекущийДокумент()));
        СтатусВозврата(0);
        Возврат;
    КонецПопытки;
    
    // если сюда добрались, значит можно все проводить
    КонтФормы = "Проводить";
    ОткрытьФорму("Обработка.ПроведениеИзМодуляПроведения", КонтФормы);
    
КонецПроцедуры  

//******************************************************************************
Процедура ОбработкаУдаленияПроведения()        
    
    // возвращаем в документ-основание номенклатуру
    Док = СоздатьОбъект("Документ");
    Док.НайтиДокумент(ДокОснование);
    ВыбратьСтроки();
    Пока ПолучитьСтроку() > 0 Цикл
        Док.ВыбратьСтроки();
        НомерНайденнойСтроки = 0;
        Пока Док.ПолучитьСтроку() > 0 Цикл
            Если Док.Номенклатура <> Номенклатура Тогда
                Продолжить;
            КонецЕсли;            
            НомерНайденнойСтроки = Док.НомерСтроки;
        КонецЦикла;
        Если НомерНайденнойСтроки = 0 Тогда
            Док.НоваяСтрока();
            Док.Номенклатура = Номенклатура;
            Док.Количество = Количество;
            Док.Единица = Единица;
            Док.Коэффициент = Коэффициент;
            Док.Цена = Цена;
            Док.СтавкаНДС = СтавкаНДС;
            Док.СтавкаНП = СтавкаНП;
        Иначе
            Док.ПолучитьСтрокуПоНомеру(НомерНайденнойСтроки);
            Док.Количество = Док.Количество + Количество;
        КонецЕсли;
        глПересчетТаблЧасти(Док, "Количество");
    КонецЦикла;

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


См. также

Подписаться Добавить вознаграждение

Комментарии

1. AlexQC (alexqc) 06.11.06 15:30
Нехорошо менять существующие документы - корректнее делать сторно. И зачем генерировать новые документы, с гемороем с перепроведением и отслеживанием изменений?

ИМХО, надо было бы ограничится единственным документом - "недовозом", который бы:
1. Кидал бы недовезенные позиции на склад для разборок;
2. Снимал бы с клиента взаиморасчеты на сумму недовоза.
3. А при желании - можно было еще и движения заявок сделать. Может так бы на самом деле удобнее оказалось (типа клиент же это хотел).
при чем никаких расчетов регистров документ не тянет - все точно по движениям исходного документа-основания. С обратным знаком.
2. Иван (Ioann) 07.11.06 12:45
1. А каким же образом в случае сторно получить нормальные отгрузочные документы, которые должны попасть клиенту и ... в налоговую базу?
2. Информация о недовозе приходит через день, два, три ... с момента отгрузки. Документ недовоз вводится именно тогда, когда поступила об этом информация - а все движения сразу после отгрузки.
3. " ... И зачем генерировать новые документы, с геморроем с перепроведением и отслеживанием изменений" - именно это у меня решенено без всяких геморроев, при этом совершенно не нужно заботиться о движениях по регистрам и проводках - это все делают стандартно документы "Перемещение ТМЦ" и "Снятие резерва" - одни и те же операции в одном месте, а не разбросаны по разным документам. Сам документ "Акт недовоза" при этом в последовательность не входит.
3. Иван (Ioann) 07.11.06 13:45
В догонку: как по бюстгалтерии будет проходить снятие взаиморасчетов?
4. Сhe Burashka (CheBurator) 09.11.06 23:30
Толком не почитал, но отложил - ибо для меня это больная проблема и статью я изучу с очень большой тщательностью - я=покупатель и мне постоянно недовозят поставщики (в основном один самый крупный), причем моих "недовозов" моим покупателям гораздо меньше, чем от моего поставщика мне - о чем это говорит? (и пример автора это только подтверждает) - недостаточное внимание уделено технологии работы склада/отгрузки/приходования и прочего в фирме у автора этой статьи (т.е. чем крупнее фирма - тем больше усилий надо направлять на управление "потоками бизнес-процессов" - а получается, был оборот 20 млн, стал 200 млн, а "режим" работы как был так и остался - и поперли косяки плотной стаей...). Имхо - наведя порядок и "отравняв" технологические процессы (даже самую простую "логистику") удалось бы добиться гораздо более внушительных результатов, чем с помощью "акта недовоза". вот и получается - хозяину надо тратиться на деньги для постановки "технологических процессов" - а то ли жаба давит, толи спецов нет - в итоге программеры решают полувысосанные из пальца задачи... и все хорошо, недовозы как были - так и остались - только теперь все при деле - все автоматизировано, девочки недовозы в базу шарашат (за зарплату между прочим) -итого деньги все равно уходят... причем ПОСТОЯННО, а не единоразово на постановку учета... а покупатель как трахался с поставщиком по недовозам - так и трахается... сорри, что немного эмоционально - очень уж близко это мне...

Снятие взаиморасчетов вбухии - имхо должно проходить только по акту недостачи со стороны покупателя - об этом в статье что-нибудь есть?
5. Иван (Ioann) 10.11.06 11:04
Сразу по поводу последней фразы, насчет взаиморасчетов - этот вопрос я задавал Алексею на его предложение о снятии взаиморасчетов. В статье о взаиморасчетах не слова, только в коде, если внимательно смотреть.
А вообще я не ожидал такой пользовательской реакции по поводу статьи, особенно от Чебурашки - советую прочитать внимательно. Цель статьи продемонстрировать именно процесс автоматизации и те моменты, которые пришлось решать по ходу - именно это я старался описать, а не саму задачу. Похоже надо было в клубе выкладывать...
Что касается самого факта недовоза - это результат принятия товара покупателем, а не недопоставка, связанная с логистикой и управлением складом. Об автоматизации этого я тоже могу понаписать... Решив все задачи и отгрузив в срок именно то, что заказал покупатель, недовозы все равно могут быть.
6. Иван (Ioann) 10.11.06 11:20
У меня по предполагаемым недопоставкам, заинтересованным пользователям автоматически выдаются сообщения и это не помогает решить задачу, так что дело не в автоматизации. А задачу по автоматизации недовоза, между прочим, мне никто не ставил - я сам себе её поставил, посмотрев на работу отдела отгрузок, как раз с целью уменьшения работы оператора и количества ошибок.
7. ЧеБуратор 12.11.06 16:00
> особенно от Чебурашки - советую прочитать внимательно. Цель статьи продемонстрировать именно процесс автоматизации и те моменты, которые пришлось решать по ходу

А что я такого сказал? ясен пень - буду читать еще раз очень внимательно
8. Сhe Burashka (CheBurator) 04.03.07 05:36
Почитал еще раз... много верного...
9. Александр Прокопенко (babylon_5) 05.07.07 12:28
Вот этот кусочек комментария в процедуре обработки удаления проведения:
// при отмене проведения делаем не проведенным
// помечать на удаление будем при пометке на удаление самого акта

Как отловить программно пометку на удаление документа чтобы удалить и подчиненный?
10. Сhe Burashka (CheBurator) 05.07.07 22:16
Существет предопределенная процедура в глобальном модуле
11. Александр Прокопенко (babylon_5) 06.07.07 00:00
12. Вадим Никонов (V.Nikonov) 23.12.09 15:03
Нескоко похожа задача оформления возврата от покупателя через корректировку документов отгрузки. У меня не стояло задачи документального оформления данной операции (поэтому ограничился добавлением в комментарии). Задачу решал созданием обработки: Она уменьшала состав накладной; переводила снятое количество в документ перемещения (т.к. задача решалась в 1С8 УТ, то перемещение по ордерной схеме). В случае реализации в ТиС придётся использовать специальный склад временного пребывания.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа