пятница, 12 июня 2009 г.

1С: УСН: Пиво на дом: Скидки

В данной статье я хочу предложить один из вариантов реализации скидок.
Итак соберем во едино всю информацию:
  1. В системе нет схожего механизма (делать необходимо "с нуля")
  2. На будущее необходимо заложить весь механизм скидок
Как мне показалось рациональнее всего скидки хранить в справочниках, во-первых механизм управления проще реализовать, во-вторых структура будет понятна любому пользователю (не мне же забивать).
Итак структура справочника:

  • Наименование - для того чтобы идентифицировать скидку в системе
  • Размер - размер скидки
  • Действует (Да/Нет) - Действует ли данная скидка
  • Для дня рождения (Да/Нет) - Использовать ли данную скидку для дня рождения. Это уникальная скидка которая действует в день рождения клиента
  • Список товаров - список товаров на которые действует данная скидка
т.к. организация только набирает свои обороты для начала я сделал скидку для дня рождения.
Что для этого нужно было сделать:

  • Создать справочник скидок в соответствии с вышеприведенной структурой
  • Добавить в документ новое поле "Скидка", где будет сохранятся скидка по товару
  • При открытии проверять было ли ДР у клиента в дату накладной, при успехе поднимать флаг уникальной скидки
  • При указании количества товара, вычислять скидку. В данном случае только если флаг ДР поднят
  • Дополнить печатную форму информацией о скидках
  • Поздравить клиента с днем рождения
Итак по порядку. Создал справочник, сделал необходимые поля. Долго размышлял по поводу как хранить список товаров. Надумал несколько вариантов:
  1. Использовать строку неограниченной длинны и записывать коды товаров через запятую.(Легко переводится в список товаров и обратно)
  2. Использовать "Неопределенный тип" и назначить ему список значений
  3. В товаре создать поле "скидка" с типом "Справочник.Скидки" и выбирать по этому полю
Решил выбрать первый вариант по следующим причинам: 3 вариант не подходит т.к. не удастся реализовать отношение "многие ко многим". 2 вариант не стал использовать т.к. как то пытался использовать неопределенный тип в справочнике, что-то не пошло. А вот первый вариант оказался очень прост в исполнении.
В главный модуль добавил:

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

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

Комментариев нет:

Отправить комментарий