ДЛЯ КОГО
Для финансового директора - для понимания, что не Excel'ем единым жив финансовый и управленческий учет.
Для программиста - для понимания, как внедрить предлагаемую финансово-управленческую модель.
ПРО ЧТО
Вашему вниманию представлена статья - пошаговое внедрение в УТ 10.3 финансово-управленческой модели "Согласования цен по заказу покупателя или счету на оплату покупателя" без использования объектов метаданных "Бизнес-процессы" и "Задачи", без использования дополнительных специальных подсистем документооборота.
Подобная фин.-упр. модель не реализована типовым функционалом в УТ 10.3, поэтому потребовалась доработка УТ 10.3. Как и любая модель имеет свои допущения и ограничения. Внедрялась на конкретном предприятии с конкретными бизнес-процессами, и поэтому не претендует на универсальность.
Краткое описание
На предприятии используется сетка цен - разные категории цен с разными скидками от "основной" цены по прайсу.
Ряд категорий используются только менеджерами - для них включен признак "Показывать менеджерам", остальные категории им не доступны для использования.
Согласование цен по заказу покупателя (счету на оплату) происходит так.
Сначала опишу стандартный типовой сценарий работы с ценами. В настройках каждого пользователя можно указать - с какой ценой по-умолчанию работает каждый менеджер.
Тогда у менеджера при создании заказа на каждый товар устанавливается автоматом цена по прайсу. Далее, менеджер может выбрать другую категорию цен из раздела "Цены и валюты". Цены перезаполняются по новой категории.
У каждого менеджера есть ограничение, что ниже определенной категории цены документ проводить нельзя.
На этом типовые механизмы в части игр с ценами заканчиваются.
Далее опишу свою разработку. При необходимости менеджер может снизить цену на товар - он указывает новую цену в отдельной колонке "Цена новая" с признаком "На согласование". Сам признак - это тоже отдельная колонка.
Руководитель постоянно мониторит список заказов. В форме имеется подсказка и фильтр на заказы, которые надо согласовать.
Мониторинг заказов на согласование
//доработка+
Процедура НаСогласованиеПриИзменении(Элемент)
Если НаСогласование Тогда
ДокументСписок.Отбор.НаСогласование.Установить(Истина);
Иначе
ДокументСписок.Отбор.НаСогласование.Использование = Ложь;
КонецЕсли;
КонецПроцедуры
//доработка+
Процедура ОбновлениеОтображения()
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ЗаказПокупателя.Ссылка
|ИЗ
| Документ.ЗаказПокупателя КАК ЗаказПокупателя
|ГДЕ
| ЗаказПокупателя.НаСогласование = ИСТИНА
| И ЗаказПокупателя.ПометкаУдаления = ЛОЖЬ";
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
ЭлементыФормы.НаСогласование.Заголовок = "На согласование" + ?(Выборка.Количество() = 0, "", " " + Выборка.Количество() + " док.");
КонецПроцедуры
Руководитель открывает заказ, напротив каждой позиции визирует "Согласовано".
Признак "Согласовано" - это отдельная колонка. При этом сумма по строке пересчитывается, фиксируется "Ответственный за согласование" и "Дата согласования" (см. код ниже).
Алгоритм визирования "Согласовано"
Процедура ТоварыПриИзмененииФлажка(Элемент, Колонка)
Если Колонка <> Элемент.Колонки.Согласовано Тогда
Возврат;
КонецЕсли;
ТекДанные = Элемент.ТекущиеДанные;
Если ТекДанные.Согласовано Тогда
ТекДанные.ОтветственныйЗаСогласование = глЗначениеПеременной("глТекущийПользователь");
ТекДанные.ДатаСогласования = ТекущаяДата();
МодульДоработок.РассчитатьСуммуТабЧасти(ТекДанные, ЭтотОбъект);
Иначе
ТекДанные.ОтветственныйЗаСогласование = Неопределено;
ТекДанные.ДатаСогласования = Неопределено;
ОбработкаТабличныхЧастей.РассчитатьСуммуТабЧасти(ТекДанные, ЭтотОбъект);
КонецЕсли;
ОбработкаТабличныхЧастей.РассчитатьСуммуНДСТабЧасти(ТекДанные, ЭтотОбъект);
КонецПроцедуры
Далее документ проводится и закрывается. При проведении программа проверит категорию цен Ответственного за согласование - чтобы не опуститься по цене ниже его категории. Поскольку у руководителя также установлено стандартное ограничение цен по "минимальной" категории.
Менеджер может продолжить редактировать заказ - добавлять новые товары - при этом согласованные строки товаров становятся не редактируемыми для всех пользователей, кроме Ответственного за согласование (см. код ниже).
Блокировка согласованной строки товаров
Процедура ТоварыПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
...
//после согласования редактировать строку может только руководитель, который согласовал новую цену
Если ДанныеСтроки.Согласовано И ДанныеСтроки.ОтветственныйЗаСогласование <> глЗначениеПеременной("глТекущийПользователь") Тогда
ОформлениеСтроки.Ячейки.Номенклатура.ТолькоПросмотр = Истина;
ОформлениеСтроки.Ячейки.Количество.ТолькоПросмотр = Истина;
ОформлениеСтроки.Ячейки.Цена.ТолькоПросмотр = Истина;
ОформлениеСтроки.Ячейки.Сумма.ТолькоПросмотр = Истина;
ОформлениеСтроки.Ячейки.ЦенаНовая.ТолькоПросмотр = Истина;
ОформлениеСтроки.Ячейки.НаСогласование.ТолькоПросмотр = Истина;
ОформлениеСтроки.Ячейки.Согласовано.ТолькоПросмотр = Истина;
ОформлениеСтроки.Ячейки.СуммаНДС.ТолькоПросмотр = Истина;
ОформлениеСтроки.Ячейки.СтавкаНДС.ТолькоПросмотр = Истина;
ОформлениеСтроки.Ячейки.ПроцентСкидкиНаценки.ТолькоПросмотр = Истина;
ОформлениеСтроки.Ячейки.Единица.ТолькоПросмотр = Истина;
Иначе
ОформлениеСтроки.Ячейки.Номенклатура.ТолькоПросмотр = Ложь;
ОформлениеСтроки.Ячейки.Количество.ТолькоПросмотр = Ложь;
ОформлениеСтроки.Ячейки.Цена.ТолькоПросмотр = Ложь;
ОформлениеСтроки.Ячейки.Сумма.ТолькоПросмотр = Ложь;
ОформлениеСтроки.Ячейки.ЦенаНовая.ТолькоПросмотр = Ложь;
ОформлениеСтроки.Ячейки.НаСогласование.ТолькоПросмотр = Ложь;
ОформлениеСтроки.Ячейки.Согласовано.ТолькоПросмотр = Ложь;
ОформлениеСтроки.Ячейки.СуммаНДС.ТолькоПросмотр = Ложь;
ОформлениеСтроки.Ячейки.СтавкаНДС.ТолькоПросмотр = Ложь;
ОформлениеСтроки.Ячейки.ПроцентСкидкиНаценки.ТолькоПросмотр = Ложь;
ОформлениеСтроки.Ячейки.Единица.ТолькоПросмотр = Ложь;
КонецЕсли;
КонецПроцедуры // ТоварыПриВыводеСтроки()
Архитектура решения
В документ "Заказ покупателя" добавлены следующие реквизиты:
1) в шапку документа - реквизит "НаСогласование" - который хранит информацию "надо ли согласовывать данный заказ". Определяется перед записью документа (см. код ниже). Реквизит является служебным - на форме заказа не отображается.
2) в табличную часть "Товары" - добавлены колонки "НаСогласование", "ЦенаНовая", "Согласовано", "ОтветственныйЗаСогласование", "ДатаСогласования".
Дата согласования нужна, чтобы проверять условие "цена действительна в течение 7 календарных дней", иначе будет выдано сообщение с блокировкой проведения "Необходимо пересогласовать цену". Ниже указаны алгоритмы проверок перед записью документа.
Проверки перед записью документа
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
...
//доработка+
НаСогласование = Ложь;
Для Каждого Стр Из Товары Цикл
Если Стр.НаСогласование И НЕ Стр.Согласовано Тогда
НаСогласование = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
//доработка+
Для Каждого Стр Из Товары Цикл
Если Стр.НаСогласование И Стр.ЦенаНовая = 0 Тогда
Сообщить("Строка " + Стр.НомерСтроки + " - не задана цена на согласование!");
Отказ = Истина;
Возврат;
КонецЕсли;
КонецЦикла;
//доработка+
Для Каждого Стр Из Товары Цикл
Если НЕ Стр.НаСогласование Тогда //все нормально
Продолжить;
КонецЕсли;
ПараметрыОтбора = Новый Структура;
ПараметрыОтбора.Вставить("Номенклатура", Стр.Номенклатура);
НайденныеСтроки = Товары.НайтиСтроки(ПараметрыОтбора);
Если НайденныеСтроки.Количество() = 1 Тогда //все нормально
Продолжить;
КонецЕсли;
ЦеныРазные = Ложь;
Для Каждого НайденнаяСтр Из НайденныеСтроки Цикл
Если НайденнаяСтр.НомерСтроки = Стр.НомерСтроки Тогда
Продолжить;
КонецЕсли;
Если НайденнаяСтр.ЦенаНовая<>Стр.ЦенаНовая
ИЛИ НайденнаяСтр.Цена<>Стр.Цена
ИЛИ НайденнаяСтр.НаСогласование<>Стр.НаСогласование
ИЛИ НайденнаяСтр.Согласовано<>Стр.Согласовано Тогда
ЦеныРазные = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
ТекстСообщения = "Нельзя записывать заказ с разными ценами,"
+ Символы.ПС + " с разными ценами на согласование,"
+ Символы.ПС + " с разными отметками ""На согласование"" и ""Согласовано"" по одной номенклатуре!";
ТекстСообщения = ТекстСообщения + Символы.ПС + Стр.Номенклатура + Символы.ПС + "строки " + Стр.НомерСтроки + " и " + НайденнаяСтр.НомерСтроки;
Если ЦеныРазные Тогда
Сообщить(ТекстСообщения);
Отказ = Истина;
Возврат;
КонецЕсли;
КонецЦикла;
//доработка+
ДатаМинимум = Дата(2100,1,1);
НомерСтроки = 0;
Для Каждого Стр Из Товары Цикл
Если ЗначениеЗаполнено(Стр.ДатаСогласования) И Стр.Согласовано И Стр.ДатаСогласования<ДатаМинимум Тогда
ДатаМинимум = Стр.ДатаСогласования;
НомерСтроки = Стр.НомерСтроки;
КонецЕсли;
КонецЦикла;
Если НомерСтроки<>0 И ДатаМинимум<>Дата(2100,1,1) И (НачалоДня(Дата) - ДатаМинимум)/3600/24 > 7 Тогда
Отказ = Истина;
Сообщить("Прошло более 7-и календарных дней - надо пересогласовать цену по строке " + НомерСтроки);
КонецЕсли;
КонецПроцедуры // ПередЗаписью()
В модуле документа "Заказ покупателя" для проведения по регистру накопления "Заказы покупателей" переопределяется функция ПодготовитьТаблицуТоваров(). Этого достаточно, чтобы в движения заказа "села" согласованная новая цена (см. код ниже).
Функция ПодготовитьТаблицуТоваров(...)
Функция ПодготовитьТаблицуТоваров(РезультатЗапросаПоТоварам, СтруктураШапкиДокумента)
...
//доработка+
Для Каждого Стр Из ТаблицаТоваров Цикл
Если Стр.Согласовано Тогда
Стр.Цена = Стр.ЦенаНовая;
КонецЕсли;
КонецЦикла;
Возврат ТаблицаТоваров;
КонецФункции // ПодготовитьТаблицуТоваров()
В процедуре ОбработкаПроведения() переопределяется процедура ПроверитьДопустимостьЦенОтпуска(ДокументОбъект, ИмяТабличнойЧасти, Отказ).
Доработка процедуры ПроверитьДопустимостьЦенОтпуска(ДокументОбъект, ИмяТабличнойЧасти, Отказ)
Процедура ПроверитьДопустимостьЦенОтпуска(ДокументОбъект, ИмяТабличнойЧасти, Отказ) Экспорт
//доработка+
Если (ТипЗнч(ДокументОбъект) = Тип("ДокументОбъект.СчетНаОплатуПокупателю")
ИЛИ ТипЗнч(ДокументОбъект) = Тип("ДокументОбъект.ЗаказПокупателя")
ИЛИ ТипЗнч(ДокументОбъект) = Тип("ДокументОбъект.РеализацияТоваровУслуг"))
И ИмяТабличнойЧасти = "Товары" Тогда
МодульДоработок.ПроверитьДопустимостьЦенОтпуска(ДокументОбъект, ИмяТабличнойЧасти, Отказ);
Возврат;
КонецЕсли;
//остальной код типовой без изменений:
...
КонецПроцедуры
Первая половина алгоритма переопределяемой процедуры - типовая, и все же я представляю полный листинг процедуры - чтобы можно было скопировать в свою конфигурацию. А в следующем абзаце описана суть изменений - по сути ядро модели.
Переопределение процедуры ПроверитьДопустимостьЦенОтпуска
Процедура ПроверитьДопустимостьЦенОтпуска(ДокументОбъект, ИмяТабличнойЧасти, Отказ) Экспорт
Запрос = Новый Запрос;
МетаданныеДокумента = ДокументОбъект.Метаданные();
ИмяДокумента = МетаданныеДокумента.Имя;
ЕстьХарактеристикаНоменклатуры = ОбщегоНазначения.ЕстьРеквизитТабЧастиДокумента("ХарактеристикаНоменклатуры", МетаданныеДокумента, ИмяТабличнойЧасти);
ДополнительныеПоля = "";
ЛевоеСоединение = "";
ПоляДляОбъединенияЗапросов = "";
СписокФильтров = УправлениеПользователями.ПолучитьЗначениеПраваДляТекущегоПользователя(ПланыВидовХарактеристик.ПраваПользователей.НеОтпускатьТоварСЦенойНижеОпределенногоТипа, Неопределено);
НомерТипаЦен = 0;
Для Каждого ТипЦены Из СписокФильтров Цикл
Если НЕ ЗначениеЗаполнено(ТипЦены.Значение) Тогда
// Если хотя бы для одного набора прав не задан тип цен, ниже которого нельзя продавать,
// то значит можно продавать по любой цене.
Возврат;
КонецЕсли;
НомерТипаЦен = НомерТипаЦен + 1;
Запрос.УстановитьПараметр("ДатаСреза", ДокументОбъект.Ссылка.Дата);
Запрос.УстановитьПараметр("ЦенаВключаетНДС" + НомерТипаЦен, ТипЦены.Значение.ЦенаВключаетНДС);
Если ТипЦены.Значение.Рассчитывается Тогда
Запрос.УстановитьПараметр("ТипЦен" + НомерТипаЦен, ТипЦены.Значение.БазовыйТипЦен);
Запрос.УстановитьПараметр("ТипЦенДинамический" + НомерТипаЦен, ТипЦены.Значение);
Запрос.УстановитьПараметр("Коэффициент" + НомерТипаЦен, ТипЦены.Значение.ПроцентСкидкиНаценки);
Иначе
Запрос.УстановитьПараметр("ТипЦен" + НомерТипаЦен, ТипЦены.Значение);
Запрос.УстановитьПараметр("Коэффициент" + НомерТипаЦен, 0);
КонецЕсли;
ЛевоеСоединение = ЛевоеСоединение + "
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&ДатаСреза, ТипЦен = &ТипЦен" + НомерТипаЦен + " И (Номенклатура" + ?(ЕстьХарактеристикаНоменклатуры, ", ХарактеристикаНоменклатуры", "") + ") В (ВЫБРАТЬ РАЗЛИЧНЫЕ Док.Номенклатура " + ?(ЕстьХарактеристикаНоменклатуры, ", Док.ХарактеристикаНоменклатуры", "")+ " ИЗ Документ." + ИмяДокумента + "."+ИмяТабличнойЧасти+" КАК Док ГДЕ Док.Ссылка = &ДокументСсылка)) КАК ЦеныКомпании" + НомерТипаЦен + "
| ПО ЦеныКомпании" + НомерТипаЦен + ".Номенклатура = Док.Номенклатура";
Если ЕстьХарактеристикаНоменклатуры Тогда
Запрос.УстановитьПараметр("ПустаяХарактеристикаНоменклатуры" , Справочники.ХарактеристикиНоменклатуры.ПустаяСсылка());
ЛевоеСоединение = ЛевоеСоединение + "
| И
| ЦеныКомпании" + НомерТипаЦен + ".ХарактеристикаНоменклатуры = Док.ХарактеристикаНоменклатуры
|
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&ДатаСреза, ТипЦен = &ТипЦен" + НомерТипаЦен + " И (Номенклатура, ХарактеристикаНоменклатуры) В (ВЫБРАТЬ РАЗЛИЧНЫЕ Док.Номенклатура , ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка) КАК ХарактеристикаНоменклатуры ИЗ Документ." + ИмяДокумента + "."+ИмяТабличнойЧасти+" КАК Док ГДЕ Док.Ссылка = &ДокументСсылка)) КАК ЦеныКомпанииБезХарактеристики" + НомерТипаЦен + "
| ПО ЦеныКомпанииБезХарактеристики" + НомерТипаЦен + ".Номенклатура = Док.Номенклатура
| И
| ЦеныКомпанииБезХарактеристики" + НомерТипаЦен + ".ХарактеристикаНоменклатуры = &ПустаяХарактеристикаНоменклатуры
|";
ДополнительныеПоля = ДополнительныеПоля + "," + "
| &ЦенаВключаетНДС" + НомерТипаЦен +" КАК ЦенаВключаетНДС" + НомерТипаЦен +",
| &Коэффициент" + НомерТипаЦен +" КАК ПроцентСкидкиНаценкиИзСправочника" + НомерТипаЦен +",
| ВЫБОР КОГДА ЦеныКомпании" + НомерТипаЦен + ".Цена ЕСТЬ NULL ТОГДА
| ЦеныКомпанииБезХарактеристики" + НомерТипаЦен + ".Цена
| ИНАЧЕ ЦеныКомпании" + НомерТипаЦен + ".Цена КОНЕЦ КАК Цена" + НомерТипаЦен;
Если ТипЦены.Значение.Рассчитывается Тогда
ДополнительныеПоля = ДополнительныеПоля + "," + "
| ВЫБОР КОГДА ЦеныКомпании" + НомерТипаЦен + ".Цена ЕСТЬ NULL ТОГДА
| ВложенныйЗапросБезХарактеристики" + НомерТипаЦен +".ПроцентСкидкиНаценкиБезХарактеристики
| ИНАЧЕ ВложенныйЗапрос" + НомерТипаЦен +".ПроцентСкидкиНаценки КОНЕЦ КАК ПроцентСкидкиНаценки" + НомерТипаЦен;
КонецЕсли;
ДополнительныеПоля = ДополнительныеПоля + "," + "
| ВЫБОР КОГДА ЦеныКомпании" + НомерТипаЦен + ".Цена ЕСТЬ NULL ТОГДА
| ЦеныКомпанииБезХарактеристики" + НомерТипаЦен + ".Валюта
| ИНАЧЕ ЦеныКомпании" + НомерТипаЦен + ".Валюта КОНЕЦ КАК Цена" + НомерТипаЦен + "Валюта,
| ВЫБОР КОГДА ЦеныКомпании" + НомерТипаЦен + ".Цена ЕСТЬ NULL ТОГДА
| ЦеныКомпанииБезХарактеристики" + НомерТипаЦен + ".ЕдиницаИзмерения
| ИНАЧЕ ЦеныКомпании" + НомерТипаЦен + ".ЕдиницаИзмерения КОНЕЦ КАК Цена" + НомерТипаЦен + "Единица
|";
Иначе
ДополнительныеПоля = ДополнительныеПоля + "," + "
| &ЦенаВключаетНДС" + НомерТипаЦен +" КАК ЦенаВключаетНДС" + НомерТипаЦен;
Если ТипЦены.Значение.Рассчитывается Тогда
ДополнительныеПоля = ДополнительныеПоля + "," + "
| ЦеныКомпании" + НомерТипаЦен + ".Цена * (1 + ВложенныйЗапрос" + НомерТипаЦен +".ПроцентСкидкиНаценки / 100) КАК Цена" + НомерТипаЦен + ",
| ЦеныКомпании" + НомерТипаЦен + ".Валюта КАК Цена" + НомерТипаЦен + "Валюта,
| ЦеныКомпании" + НомерТипаЦен + ".ЕдиницаИзмерения КАК Цена" + НомерТипаЦен + "Единица";
Иначе
ДополнительныеПоля = ДополнительныеПоля + "," + "
| ЦеныКомпании" + НомерТипаЦен + ".Цена КАК Цена" + НомерТипаЦен + ",
| ЦеныКомпании" + НомерТипаЦен + ".Валюта КАК Цена" + НомерТипаЦен + "Валюта,
| ЦеныКомпании" + НомерТипаЦен + ".ЕдиницаИзмерения КАК Цена" + НомерТипаЦен + "Единица";
КонецЕсли;
КонецЕсли;
Если ТипЦены.Значение.Рассчитывается Тогда
ЛевоеСоединение = ЛевоеСоединение + "
| ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
| ДинамическиеЦеныКомпании" + НомерТипаЦен + ".ПроцентСкидкиНаценки КАК ПроцентСкидкиНаценки,
| ДинамическиеЦеныКомпании" + НомерТипаЦен + ".Номенклатура КАК Номенклатура";
Если ЕстьХарактеристикаНоменклатуры Тогда
ЛевоеСоединение = ЛевоеСоединение + ",
| ДинамическиеЦеныКомпании" + НомерТипаЦен + ".ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры";
КонецЕсли;
ЛевоеСоединение = ЛевоеСоединение + "
| ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&ДатаСреза, ТипЦен = &ТипЦенДинамический" + НомерТипаЦен + " И (Номенклатура" + ?(ЕстьХарактеристикаНоменклатуры, ", ХарактеристикаНоменклатуры", "") + ") В (ВЫБРАТЬ РАЗЛИЧНЫЕ Док.Номенклатура " + ?(ЕстьХарактеристикаНоменклатуры, ", Док.ХарактеристикаНоменклатуры", "")+ " ИЗ Документ." + ИмяДокумента + "."+ИмяТабличнойЧасти+" КАК Док ГДЕ Док.Ссылка = &ДокументСсылка)
| ) КАК ДинамическиеЦеныКомпании" + НомерТипаЦен;
ЛевоеСоединение = ЛевоеСоединение + "
| )КАК ВложенныйЗапрос" + НомерТипаЦен +"
| ПО ЦеныКомпании" + НомерТипаЦен + ".Номенклатура = ВложенныйЗапрос" + НомерТипаЦен +".Номенклатура";
Если ЕстьХарактеристикаНоменклатуры Тогда
ЛевоеСоединение = ЛевоеСоединение + "
| И ЦеныКомпании" + НомерТипаЦен + ".ХарактеристикаНоменклатуры = ВложенныйЗапрос" + НомерТипаЦен +".ХарактеристикаНоменклатуры";
КонецЕсли;
Если ЕстьХарактеристикаНоменклатуры Тогда
ЛевоеСоединение = ЛевоеСоединение + "
| ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
| ДинамическиеЦеныКомпанииБезХарактеристики" + НомерТипаЦен + ".Номенклатура КАК Номенклатура,
| ДинамическиеЦеныКомпанииБезХарактеристики" + НомерТипаЦен + ".ПроцентСкидкиНаценки
| КАК ПроцентСкидкиНаценкиБезХарактеристики
| ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&ДатаСреза, ТипЦен = &ТипЦенДинамический" + НомерТипаЦен + " И (Номенклатура, ХарактеристикаНоменклатуры) В (ВЫБРАТЬ РАЗЛИЧНЫЕ Док.Номенклатура , ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка) КАК ХарактеристикаНоменклатуры ИЗ Документ." + ИмяДокумента + "."+ИмяТабличнойЧасти+" КАК Док ГДЕ Док.Ссылка = &ДокументСсылка)
| ) КАК ДинамическиеЦеныКомпанииБезХарактеристики" + НомерТипаЦен;
ЛевоеСоединение = ЛевоеСоединение + "
| )КАК ВложенныйЗапросБезХарактеристики" + НомерТипаЦен +"
| ПО ЦеныКомпании" + НомерТипаЦен + ".Номенклатура = ВложенныйЗапрос" + НомерТипаЦен +".Номенклатура";
КонецЕсли;
КонецЕсли;
КонецЦикла;
ВалютаРегламентированногоУчета = глЗначениеПеременной("ВалютаРегламентированногоУчета");
Запрос.УстановитьПараметр("ВалютаРеглУчета", ВалютаРегламентированногоУчета);
Запрос.Текст = "
|ВЫБРАТЬ
| Док.Номенклатура,
| "+?(ОбщегоНазначения.ЕстьРеквизитТабЧастиДокумента("ЕдиницаИзмерения", МетаданныеДокумента, ИмяТабличнойЧасти),"Док.ЕдиницаИзмерения", "Док.Номенклатура.ЕдиницаХраненияОстатков")+" КАК ЕдиницаИзмерения,
| "+?(ОбщегоНазначения.ЕстьРеквизитТабЧастиДокумента("СтавкаНДС", МетаданныеДокумента, ИмяТабличнойЧасти),"Док.СтавкаНДС,", "")+"
| ВЫБОР КОГДА Количество = 0 ТОГДА Док.Цена ИНАЧЕ Док.Сумма/Док.Количество КОНЕЦ КАК Цена,
| "+?(ОбщегоНазначения.ЕстьРеквизитДокумента("ВалютаДокумента", МетаданныеДокумента),"Док.Ссылка.ВалютаДокумента", "&ВалютаРеглУчета")
+" КАК ВалютаДокумента,
| Док.НомерСтроки
|" + ДополнительныеПоля + "
|
|ИЗ
| Документ." + ИмяДокумента + "."+ИмяТабличнойЧасти+" КАК Док
|" + ЛевоеСоединение + "
|ГДЕ
| Док.Ссылка = &ДокументСсылка
|";
// Установим параметры запроса.
Запрос.УстановитьПараметр("ДокументСсылка" , ДокументОбъект.Ссылка);
РезультатЗапроса = Запрос.Выполнить();
ПроверилиНаличиеЦенВЗапросе = Ложь;
СоответствиеКурсыВалют = Новый Соответствие;
ТабличнаяЧастьТовары = Неопределено;
Контрагент = Неопределено;
Если ТипЗнч(ДокументОбъект) = Тип("ДокументОбъект.СчетНаОплатуПокупателю")
ИЛИ ТипЗнч(ДокументОбъект) = Тип("ДокументОбъект.ЗаказПокупателя") Тогда
ТабличнаяЧастьТовары = ДокументОбъект.Товары;
Контрагент = ДокументОбъект.Контрагент;
ИначеЕсли ЗначениеЗаполнено(ДокументОбъект.Сделка) Тогда //РеализацияТоваровУслуг, ДокументОбъект.Сделка - это Заказ
ТабличнаяЧастьТовары = ДокументОбъект.Сделка.Товары;
Контрагент = ДокументОбъект.Сделка.Контрагент;
КонецЕсли;
КатегорияЦенКонтрагента = Неопределено;
Если ЗначениеЗаполнено(Контрагент) И ТипЗнч(Контрагент) = Тип("СправочникСсылка.Контрагенты") Тогда
КатегорияЦенКонтрагента = Контрагент.КатегорияЦен;
КонецЕсли;
ТЗ = РезультатЗапроса.Выгрузить();
ТЗ.Колонки.Добавить("НовыйМинимумЦены"); //при согласовании руководителем
ТЗ.ЗаполнитьЗначения(0, "НовыйМинимумЦены");
ТЗ.Колонки.Добавить("ЦенаКонтрагента"); //цена контрагента, если задана
ТЗ.ЗаполнитьЗначения(1000000, "ЦенаКонтрагента");
Если ТабличнаяЧастьТовары<>Неопределено Тогда
//определим по документу-основанию согласованные цены
Для Каждого Стр Из ТабличнаяЧастьТовары Цикл
//при согласовании руководителем
Если ЗначениеЗаполнено(Стр.ОтветственныйЗаСогласование) И Стр.Согласовано Тогда
мНовыйМинимумЦены = МодульДоработок.ПолучитьНовыйМинимумЦены(Стр.ОтветственныйЗаСогласование, ДокументОбъект.Дата, Стр.Номенклатура);
ПараметрыОтбора = Новый Структура("Номенклатура");
ПараметрыОтбора.Вставить("Номенклатура", Стр.Номенклатура);
НайденныеСтрокиТЗ = ТЗ.НайтиСтроки(ПараметрыОтбора);
Для Каждого СтрТЗ Из НайденныеСтрокиТЗ Цикл
СтрТЗ.НовыйМинимумЦены = мНовыйМинимумЦены;
КонецЦикла;
КонецЕсли;
//цена контрагента, если задана
Если ЗначениеЗаполнено(КатегорияЦенКонтрагента) Тогда
ОтборЦен = Новый Структура("ТипЦен, Номенклатура");
//Прайсовые цены - Справочники.ТипыЦенНоменклатуры.НайтиПоКоду("УТ0000004")
//подразумевается, что базовый тип цен для цен контрагента - прайсовые цены
ОтборЦен.Вставить("ТипЦен", КатегорияЦенКонтрагента.БазовыйТипЦен);
ОтборЦен.Вставить("Номенклатура", Стр.Номенклатура);
ПрайсоваяЦена = РегистрыСведений.ЦеныНоменклатуры.ПолучитьПоследнее(ДокументОбъект.Дата, ОтборЦен).Цена;
//или так:
//Если ПрайсоваяЦена = 0 Тогда
// ЦенаКонтрагента = 0;
//КонецЕсли;
//или так:
Если ПрайсоваяЦена = 0 Тогда
//ничего не проверяем
Продолжить;
КонецЕсли;
//округление по арифмет. правилам
ЦенаКонтрагента = Окр(ПрайсоваяЦена * (1 + КатегорияЦенКонтрагента.ПроцентСкидкиНаценки / 100), 2);
Если ЦенаКонтрагента>0 Тогда
ПараметрыОтбора = Новый Структура("Номенклатура");
ПараметрыОтбора.Вставить("Номенклатура", Стр.Номенклатура);
НайденныеСтрокиТЗ = ТЗ.НайтиСтроки(ПараметрыОтбора);
Для Каждого СтрТЗ Из НайденныеСтрокиТЗ Цикл
СтрТЗ.ЦенаКонтрагента = ЦенаКонтрагента;
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
//Выборка = РезультатЗапроса.Выбрать();
//Пока Выборка.Следующий() Цикл
Для Каждого Выборка Из ТЗ Цикл
Если НЕ ПроверилиНаличиеЦенВЗапросе Тогда
Если РезультатЗапроса.Колонки.Найти("Цена") <> Неопределено Тогда
ПроверилиНаличиеЦенВЗапросе = Истина;
Иначе
Возврат;
КонецЕсли;
КонецЕсли;
НомерТипаЦен = 1;
ЦенаТовара = ?(НЕ ЗначениеЗаполнено(Выборка.Цена), 0, Окр(Выборка.Цена,2));
ВалютаТовара = Выборка.ВалютаДокумента;
Если СоответствиеКурсыВалют[ВалютаТовара] = Неопределено Тогда
СтруктураКурсаЦеныТовара = МодульВалютногоУчета.ПолучитьКурсВалюты(ВалютаТовара, ДокументОбъект.Дата);
КурсЦеныТовара = СтруктураКурсаЦеныТовара.Курс;
КратностьЦеныТовара = СтруктураКурсаЦеныТовара.Кратность;
СоответствиеКурсыВалют[ВалютаТовара] = СтруктураКурсаЦеныТовара;
Иначе
СтруктураКурсаЦеныТовара = СоответствиеКурсыВалют[ВалютаТовара];
КурсЦеныТовара = СтруктураКурсаЦеныТовара.Курс;
КратностьЦеныТовара = СтруктураКурсаЦеныТовара.Кратность;
КонецЕсли;
МинимальнаяЦена = 0;
Пока НомерТипаЦен <> 0 Цикл
Если РезультатЗапроса.Колонки.Найти("Цена" + НомерТипаЦен) <> Неопределено
И РезультатЗапроса.Колонки.Найти("Цена" + НомерТипаЦен + "Валюта") <> Неопределено
И РезультатЗапроса.Колонки.Найти("Цена" + НомерТипаЦен + "Единица") <> Неопределено Тогда
ЦенаПроверки = Выборка["Цена" + НомерТипаЦен];
ВалютаПроверки = Выборка["Цена" + НомерТипаЦен + "Валюта"];
ЕдиницаПроверки = Выборка["Цена" + НомерТипаЦен + "Единица"];
ЦенаВключаетНДС = Выборка["ЦенаВключаетНДС" + НомерТипаЦен];
// Считаем, что если не задана цена или валюта цены
// (нет цены данного типа для данной номенклатуры), то
// проверка прошла
Если НЕ ЗначениеЗаполнено(ВалютаПроверки)
Или НЕ ЗначениеЗаполнено(ЦенаПроверки) Тогда
МинимальнаяЦена = 0;
Прервать;
КонецЕсли;
Если РезультатЗапроса.Колонки.Найти("ПроцентСкидкиНаценки" + НомерТипаЦен) <> Неопределено Тогда
ПроцентСкидкиНаценки = Выборка["ПроцентСкидкиНаценки" + НомерТипаЦен];
КонецЕсли;
Если НЕ ЗначениеЗаполнено(ПроцентСкидкиНаценки)
И РезультатЗапроса.Колонки.Найти("ПроцентСкидкиНаценкиИзСправочника" + НомерТипаЦен) <> Неопределено Тогда
ПроцентСкидкиНаценки = Выборка["ПроцентСкидкиНаценкиИзСправочника" + НомерТипаЦен];
КонецЕсли;
Если НЕ ЗначениеЗаполнено(ПроцентСкидкиНаценки) Тогда
ПроцентСкидкиНаценки = 0;
КонецЕсли;
ЦенаПроверки = Окр(ЦенаПроверки * (1 + ПроцентСкидкиНаценки / 100), 2);
Если СоответствиеКурсыВалют[ВалютаПроверки] = Неопределено Тогда
СтруктураКурсаЦеныПроверки = МодульВалютногоУчета.ПолучитьКурсВалюты(ВалютаПроверки, ДокументОбъект.Дата);
КурсЦеныПроверки = СтруктураКурсаЦеныПроверки.Курс;
КратностьЦеныПроверки = СтруктураКурсаЦеныПроверки.Кратность;
СоответствиеКурсыВалют[ВалютаПроверки] = СтруктураКурсаЦеныПроверки;
Иначе
СтруктураКурсаЦеныПроверки = СоответствиеКурсыВалют[ВалютаПроверки];
КурсЦеныПроверки = СтруктураКурсаЦеныПроверки.Курс;
КратностьЦеныПроверки = СтруктураКурсаЦеныПроверки.Кратность;
КонецЕсли;
ЦенаПроверки = Ценообразование.ПересчитатьЦенуПриИзмененииЕдиницы(ЦенаПроверки, ЕдиницаПроверки, Выборка.ЕдиницаИзмерения);
ПересчитаннаяЦенаПроверки = МодульВалютногоУчета.ПересчитатьИзВалютыВВалюту(ЦенаПроверки,
ВалютаПроверки, ВалютаТовара,
КурсЦеныПроверки, КурсЦеныТовара,
КратностьЦеныПроверки, КратностьЦеныТовара);
ПересчитаннаяЦенаПроверки = Ценообразование.ПересчитатьЦенуПриИзмененииФлаговНалогов(ПересчитаннаяЦенаПроверки,
Перечисления.СпособыЗаполненияЦен.ПоЦенамНоменклатуры,
// ДокументОбъект.ТипЦен.ЦенаВключаетНДС,
ЦенаВключаетНДС,
ОбщегоНазначения.ЕстьРеквизитДокумента("УчитыватьНДС",МетаданныеДокумента)
И ДокументОбъект.УчитыватьНДС,
ОбщегоНазначения.ЕстьРеквизитДокумента("СуммаВключаетНДС",МетаданныеДокумента)
И ДокументОбъект.СуммаВключаетНДС,
?(ОбщегоНазначения.ЕстьРеквизитТабЧастиДокумента("СтавкаНДС",МетаданныеДокумента, ИмяТабличнойЧасти),
УчетНДС.ПолучитьСтавкуНДС(Выборка.СтавкаНДС),0));
ПересчитаннаяЦенаПроверки = Окр(ПересчитаннаяЦенаПроверки, 2);
МинимальнаяЦена = ?(НомерТипаЦен = 1, ПересчитаннаяЦенаПроверки, Мин(МинимальнаяЦена, ПересчитаннаяЦенаПроверки));
Если МинимальнаяЦена = 0 Тогда
НомерТипаЦен = 0;
Иначе
НомерТипаЦен = НомерТипаЦен + 1;
КонецЕсли;
Иначе
НомерТипаЦен = 0;
КонецЕсли;
КонецЦикла;
МинимальнаяЦенаМенеджера = МинимальнаяЦена; //или по категории или 0, если не задана
МинимальнаяЦенаРуководителя = Выборка.НовыйМинимумЦены; //или по категории или 0, если не задана
МинимальнаяЦенаКонтрагента = Выборка.ЦенаКонтрагента; //или по категории или 1000000, если не задана
МинимальноВозможнаяЦена = Мин( Мин(МинимальнаяЦенаМенеджера, МинимальнаяЦенаРуководителя), МинимальнаяЦенаКонтрагента);
Если ЦенаТовара < МинимальноВозможнаяЦена Тогда
ТекстСообщения = "Строка " + Выборка.НомерСтроки + ": "
+ "Для товара " + Выборка.Номенклатура
+ Символы.ПС + " цена за единицу ниже порогового значения (цена: "
+ Формат(ЦенаТовара, "ЧДЦ=2; ЧН=0") + " " + ВалютаТовара
+ ", минимально возможное значение должно быть: "
+ Формат(МинимальноВозможнаяЦена, "ЧДЦ=2; ЧН=0") + " " + ВалютаТовара
+ ")";
ОбщегоНазначения.СообщитьОбОшибке(ТекстСообщения, Отказ);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Вспомомгательные и дополнительные процедуры общего модуля МодульДоработок
Процедура РассчитатьСуммуТабЧасти(СтрокаТабличнойЧасти, ДокументОбъект, СпособРасчета = Неопределено) Экспорт
ИмяТабличнойЧасти = ОбщегоНазначения.ПолучитьИмяТабличнойЧастиПоСсылкеНаСтроку(СтрокаТабличнойЧасти);
МетаданныеДокумента = ДокументОбъект.Метаданные();
Сумма = СтрокаТабличнойЧасти.ЦенаНовая * СтрокаТабличнойЧасти.Количество;
СуммаСкидки = 0;
Если (СпособРасчета = Неопределено)
Или (СпособРасчета = Перечисления.СпособРасчетаСуммыДокумента.СУчетомВсехСкидок)
Или (СпособРасчета = Перечисления.СпособРасчетаСуммыДокумента.БезУчетаРучнойСкидки) Тогда
Если ОбщегоНазначения.ЕстьРеквизитТабЧастиДокумента("ПроцентАвтоматическихСкидок", МетаданныеДокумента,
ИмяТабличнойЧасти) Тогда
СуммаСкидки = Сумма * СтрокаТабличнойЧасти.ПроцентАвтоматическихСкидок / 100;
КонецЕсли;
Если (СпособРасчета <> Перечисления.СпособРасчетаСуммыДокумента.БезУчетаРучнойСкидки)Тогда
Если ОбщегоНазначения.ЕстьРеквизитТабЧастиДокумента("ПроцентСкидкиНаценки", МетаданныеДокумента, ИмяТабличнойЧасти) Тогда
СуммаСкидки = СуммаСкидки + (Сумма * СтрокаТабличнойЧасти.ПроцентСкидкиНаценки / 100);
КонецЕсли;
КонецЕсли;
КонецЕсли;
СтрокаТабличнойЧасти.Сумма = Сумма - СуммаСкидки;
КонецПроцедуры // РассчитатьСуммуТабЧасти()
Функция ПолучитьНовыйМинимумЦены(Пользователь, Дата, Номенклатура) Экспорт
//1. получим категорию цен пользователя
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ЗначенияДополнительныхПравПользователя.Значение
|ИЗ
| РегистрСведений.ЗначенияДополнительныхПравПользователя КАК ЗначенияДополнительныхПравПользователя
|ГДЕ
| ЗначенияДополнительныхПравПользователя.Пользователь = &Пользователь
| И ЗначенияДополнительныхПравПользователя.Право = &Право";
Запрос.УстановитьПараметр("Пользователь", Пользователь);
Запрос.УстановитьПараметр("Право", ПланыВидовХарактеристик.ПраваПользователей.НеОтпускатьТоварСЦенойНижеОпределенногоТипа);
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Возврат 0;
КонецЕсли;
Выборка = Результат.Выбрать();
ТипЦен = Неопределено;
Если Выборка.Следующий() Тогда
ТипЦен = Выборка.Значение;
КонецЕсли;
//2. определим базовый тип цен, процент скидки и новый минимум цен
НовыйМинимумЦены = 0;
Если ЗначениеЗаполнено(ТипЦен) Тогда
Если НЕ ТипЦен.Рассчитывается Тогда
Сообщить("Обратитесь к программисту (укажите документ) - обнаружена ситуация, которая не обрабатывается алгоритмом");
Возврат 0;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ЦеныНоменклатурыСрезПоследних.Цена
|ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
| &Период,
| ТипЦен = &ТипЦен
| И Номенклатура = &Номенклатура) КАК ЦеныНоменклатурыСрезПоследних";
Запрос.УстановитьПараметр("Период", Дата);
Запрос.УстановитьПараметр("ТипЦен", ТипЦен.БазовыйТипЦен);
Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
//округление по арифмет. правилам
Если Выборка.Следующий() Тогда
НовыйМинимумЦены = Окр(Выборка.Цена * (1 + ТипЦен.ПроцентСкидкиНаценки / 100), 2);
КонецЕсли;
КонецЕсли;
Возврат НовыйМинимумЦены;
КонецФункции
Ядро модели
В данной модели наибольшее количество изменений коснулось процедуры ПроверитьДопустимостьЦенОтпуска() - за основу взят типовой алгоритм. В начале процедуры собирается запрос, который в типовом варианте обходится в цикле как РезультатЗапроса - но я переопределил РезультатЗапроса на ТаблицуЗначений. В таблицу значений добавил свои колонки для анализа наименьшей цены - Новый МинимумЦен (см. код ниже).
Адаптация типового алгоритма проверки цен - по сути это ядро модели
//Выборка = РезультатЗапроса.Выбрать();
ТЗ = РезультатЗапроса.Выгрузить();
ТЗ.Колонки.Добавить("НовыйМинимумЦены"); //при согласовании руководителем
ТЗ.ЗаполнитьЗначения(0, "НовыйМинимумЦены");
ТЗ.Колонки.Добавить("ЦенаКонтрагента"); //цена контрагента, если задана
ТЗ.ЗаполнитьЗначения(1000000, "ЦенаКонтрагента");
Если ТабличнаяЧастьТовары<>Неопределено Тогда
//определим по документу-основанию согласованные цены
Для Каждого Стр Из ТабличнаяЧастьТовары Цикл
//при согласовании руководителем
Если ЗначениеЗаполнено(Стр.ОтветственныйЗаСогласование) И Стр.Согласовано Тогда
мНовыйМинимумЦены = МодульДоработок.ПолучитьНовыйМинимумЦены(Стр.ОтветственныйЗаСогласование, ДокументОбъект.Дата, Стр.Номенклатура);
ПараметрыОтбора = Новый Структура("Номенклатура");
ПараметрыОтбора.Вставить("Номенклатура", Стр.Номенклатура);
НайденныеСтрокиТЗ = ТЗ.НайтиСтроки(ПараметрыОтбора);
Для Каждого СтрТЗ Из НайденныеСтрокиТЗ Цикл
СтрТЗ.НовыйМинимумЦены = мНовыйМинимумЦены;
КонецЦикла;
КонецЕсли;
//цена контрагента, если задана
Если ЗначениеЗаполнено(КатегорияЦенКонтрагента) Тогда
ОтборЦен = Новый Структура("ТипЦен, Номенклатура");
//Прайсовые цены - Справочники.ТипыЦенНоменклатуры.НайтиПоКоду("УТ0000004")
//подразумевается, что базовый тип цен для цен контрагента - прайсовые цены
ОтборЦен.Вставить("ТипЦен", КатегорияЦенКонтрагента.БазовыйТипЦен);
ОтборЦен.Вставить("Номенклатура", Стр.Номенклатура);
ПрайсоваяЦена = РегистрыСведений.ЦеныНоменклатуры.ПолучитьПоследнее(ДокументОбъект.Дата, ОтборЦен).Цена;
//или так:
//Если ПрайсоваяЦена = 0 Тогда
// ЦенаКонтрагента = 0;
//КонецЕсли;
//или так:
Если ПрайсоваяЦена = 0 Тогда
//ничего не проверяем
Продолжить;
КонецЕсли;
//округление по арифмет. правилам
ЦенаКонтрагента = Окр(ПрайсоваяЦена * (1 + КатегорияЦенКонтрагента.ПроцентСкидкиНаценки / 100), 2);
Если ЦенаКонтрагента>0 Тогда
ПараметрыОтбора = Новый Структура("Номенклатура");
ПараметрыОтбора.Вставить("Номенклатура", Стр.Номенклатура);
НайденныеСтрокиТЗ = ТЗ.НайтиСтроки(ПараметрыОтбора);
Для Каждого СтрТЗ Из НайденныеСтрокиТЗ Цикл
СтрТЗ.ЦенаКонтрагента = ЦенаКонтрагента;
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
//Пока Выборка.Следующий() Цикл
Для Каждого Выборка Из ТЗ Цикл
...
МинимальнаяЦенаМенеджера = МинимальнаяЦена; //или по категории или 0, если не задана
МинимальнаяЦенаРуководителя = Выборка.НовыйМинимумЦены; //или по категории или 0, если не задана
МинимальнаяЦенаКонтрагента = Выборка.ЦенаКонтрагента; //или по категории или 1000000, если не задана
МинимальноВозможнаяЦена = Мин( Мин(МинимальнаяЦенаМенеджера, МинимальнаяЦенаРуководителя), МинимальнаяЦенаКонтрагента);
Если ЦенаТовара < МинимальноВозможнаяЦена Тогда
ТекстСообщения = "Строка " + Выборка.НомерСтроки + ": "
+ "Для товара " + Выборка.Номенклатура
+ Символы.ПС + " цена за единицу ниже порогового значения (цена: "
+ Формат(ЦенаТовара, "ЧДЦ=2; ЧН=0") + " " + ВалютаТовара
+ ", минимально возможное значение должно быть: "
+ Формат(МинимальноВозможнаяЦена, "ЧДЦ=2; ЧН=0") + " " + ВалютаТовара
+ ")";
ОбщегоНазначения.СообщитьОбОшибке(ТекстСообщения, Отказ);
КонецЕсли;
КонецЦикла;
Вот собственно и все.
Кроме основных доработок были доработаны другие алгоритмы и механизмы. Представляю в виде техзадания - по сравнению с затраченным временем на придумывание "основного ядра" механизма, эти работы заняли не так много времени.
1) Разработан механизм согласования цен в документе Счет на оплату. Механизм аналогичен механизму согласования для Заказа покупателя. (1,5 ч)
2) Доработан механизм "Заполнить и провести" в Заказе покупателя. (30 мин)
3) Разработан механизм - когда на основании согласованного Заказа создается Счет на оплату - при этом счет на оплату не нужно дополнительно согласовывать.(1 ч)
4) Разработан механизм - когда на основании согласованного Счета на оплату создается Заказ или Реализация товаров - дополнительно согласовывать созданный документ не нужно. (45 мин)
5) Доработан механизм согласования - добавление в алгоритм Даты согласования и проверки цены "на 7 календарных дней". (40 мин)
6) Доработаны печатные формы счета на оплату и заказа покупателя. (2 ч)
7) Добавление механизма учета категорий цен контрагента. Менеджер выставляет цены, далее нажимает кнопку "Проверить по ценам Контрагента". Если цена менеджера меньше, чем цена Контрагента (из карточки Контрагента), тогда данная цена копируется в колонку "НоваяЦена" и автоматом ставится галка "НаСогласование" - требуется дополнительное согласование. Если цена менеджера больше или равна цене Контрагента, то ничего не происходит. Документ проводится. (1,5 ч)
Представленный механизм был реализован на платформе 8.3.11.3034 на конфигурации версии УТ 10.3.36.1.
С пользой для клиентов, RustIG
См. также:
Как эффективно использовать Инфостарт NEW!
Список реализаций + структура подчиненности + реестр документов SALE'1sm
Список заказов поставщикам + структура подчиненности SALE'1sm
Список заказов покупателей + структура подчиненности SALE'1sm
Договоры для 1с-ника ТОП-скачиваний
Сетка расписания (Планировщик) нестанДАрт
Два механизма, которые ускорили работу бухгалтеров в 1С нестанДАрт
Мини-CRM для УТ 10.3
Расчет банковских (рабочих) дней нестанДАрт
Шаблоны кода в режиме 1С:Предприятие SALE'1sm
Доработка конфигурации Конвертация Данных
Планирование платежей. Прогнозирование прибылей и убытков
Ввод показателей план-факта БП 3.0 Know-how
Инвентаризация личного опыта Для новичков 1С
Большие запросы: взгляд на проблему нестанДАрт
Технология создания коммерческих разработок Know-how
Андроид-решение для создания заказов в 1С Know-how + нестанДАрт
Отчет Остатки и цены
Печать ценников с одной и двумя ценами 55х40, 100х60, 140х200
Загрузка данных о розничных продажах из магазинов Intimissimi (Интимиссими) и Calzedonia (Кальцедония)
Доработки обмена "УТ 10.3 - интернет-магазина Shop-Script"