Условие из сборника:
Компания занимается оптовой торговлей. Взаиморасчеты с покупателями ведутся в разрезе счетов. Покупателю выставляется счет (документ «Счет»), на основании которого далее происходит отгрузка документами «Расходная накладная», причем накладных по одному счету может быть несколько. Считается, что товар по счету в конце концов будет отгружен полностью, а накладные могут быть только на основании счета. При выставлении счета каждый раз оговаривается срок (количество дней), в который покупатель должен оплатить товар, причем срок отсчитывается относительно даты полной отгрузки товара по этому счету. В том случае, если товар по счету отгружен полностью, срок оплаты истек, а покупатель оплатил не всю сумму, ему насчитываются пени. Для расчета пеней пользователями раз в неделю формируется документ «Пени», в котором автоматически должны рассчитываться пени по формуле: «количество дней просрочки» * «% пени» * «оставшаяся сумма задолженности по счету».
Просрочка отсчитывается от даты полной отгрузки плюс срок оплаты (из
счета). Процент пеней также указывается в каждом счете. В сумму задолженности
включаются пени. Складской учет товаров не ведется. Можно считать, что документы задним числом не вводятся, но существующие документы могут перепроводиться.
При поступлении оплаты (документ «Приход денег») в первую очередь покрывается задолженность по самым старым счетам. В документе «Приход денег» указывается только покупатель и сумма, а распределение по задолженности должно происходить автоматически при проведении документа. Необходимо построить отчет для анализа состояния счетов на выбранную дату и анализ счета за период.
Компания занимается оптовой торговлей. Взаиморасчеты с покупателями ведутся в разрезе счетов. Покупателю выставляется счет (документ «Счет»), на основании которого далее происходит отгрузка документами «Расходная накладная», причем накладных по одному счету может быть несколько. Считается, что товар по счету в конце концов будет отгружен полностью, а накладные могут быть только на основании счета. При выставлении счета каждый раз оговаривается срок (количество дней), в который покупатель должен оплатить товар, причем срок отсчитывается относительно даты полной отгрузки товара по этому счету. В том случае, если товар по счету отгружен полностью, срок оплаты истек, а покупатель оплатил не всю сумму, ему насчитываются пени. Для расчета пеней пользователями раз в неделю формируется документ «Пени», в котором автоматически должны рассчитываться пени по формуле: «количество дней просрочки» * «% пени» * «оставшаяся сумма задолженности по счету».
Просрочка отсчитывается от даты полной отгрузки плюс срок оплаты (из
счета). Процент пеней также указывается в каждом счете. В сумму задолженности
включаются пени. Складской учет товаров не ведется. Можно считать, что документы задним числом не вводятся, но существующие документы могут перепроводиться.
При поступлении оплаты (документ «Приход денег») в первую очередь покрывается задолженность по самым старым счетам. В документе «Приход денег» указывается только покупатель и сумма, а распределение по задолженности должно происходить автоматически при проведении документа. Необходимо построить отчет для анализа состояния счетов на выбранную дату и анализ счета за период.
Решение:
1) Для решения потребуется 2 регистра накопления "Взаиморасчеты" и "Счета".
Структуры регистров:
Взаиморасчеты Измерения "Контрагент", "Счет" ресурс "Сумма".
Счета Измерения "Контрагент", ресурс "Сумма".
2) Документы "Расходная накладная " и 3 новых "Пени", "ПоступлениеДенег" и "Счет".
Документы будут делать движения по регистрам след. образом:
Счет ( Счет +)
Расходная накладная (Взаиморасчеты+ , Счета-)
Поступление денег "Взаиморасчеты-)
Пени(Взаиморасчеты+)
3) Документ "Счет"
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Движения.Счета.Записывать = Истина;
Движение = Движения.Счета.ДобавитьПриход();
Движение.Период = Дата;
Движение.Счет = Ссылка;
Движение.Сумма = Сумма;
КонецПроцедуры
4) Документ "Расходная накладная"
Чтобы документ вводился только на основании счета потребуется 2 процедуры
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
Если ДанныеЗаполнения = Неопределено Тогда
Отказ = Истина;
Сообщение = Новый("СообщениеПользователю");
Сообщение.Текст = "Документ можно вводить только на основании счета";
Сообщение.Сообщить();
Иначе
Счет = ДанныеЗаполнения;
Контрагент = ДанныеЗаполнения.Контрагент;
Дата = ТекущаяДата();
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Если Не ЗначениеЗаполнено(Объект.Счет) Тогда
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
6) Документ "Пени"
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Движения.Взаиморасчеты.Записывать = Истина;
Движения.Взаиморасчеты.Записать() ;
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.Взаиморасчеты");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.Счета");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
Блокировка.Заблокировать();
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| СчетаОстаткиИОбороты.Счет,
| СчетаОстаткиИОбороты.СуммаКонечныйОстаток,
| МАКСИМУМ(СчетаОстаткиИОбороты.Регистратор.Дата) КАК ДатаПолнойОтгрузки
|ПОМЕСТИТЬ Счета
|ИЗ
| РегистрНакопления.Счета.ОстаткиИОбороты(, &ТочкаИтогов, Регистратор, , ) КАК СчетаОстаткиИОбороты
|ГДЕ
| СчетаОстаткиИОбороты.СуммаКонечныйОстаток = 0
|
|СГРУППИРОВАТЬ ПО
| СчетаОстаткиИОбороты.Счет,
| СчетаОстаткиИОбороты.СуммаКонечныйОстаток
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Счета.Счет,
| ЕСТЬNULL(ВзаиморасчетыОстатки.СуммаОстаток, 0) КАК Долг,
| Счета.Счет.ПроцентПени КАК ПроцентПени,
| ВзаиморасчетыОстатки.Контрагент,
| РАЗНОСТЬДАТ(Счета.ДатаПолнойОтгрузки, &Дата, ДЕНЬ) КАК ДнейПросрочки
|ИЗ
| РегистрНакопления.Взаиморасчеты.Остатки(
| &ТочкаИтогов,
| Счет В
| (ВЫБРАТЬ
| Счета.Счет
| ИЗ
| Счета)) КАК ВзаиморасчетыОстатки
| ЛЕВОЕ СОЕДИНЕНИЕ Счета КАК Счета
| ПО ВзаиморасчетыОстатки.Счет = Счета.Счет";
Запрос.УстановитьПараметр("Дата", Дата);
ТочкаИтогов = ?(РежимПроведения= РежимПроведенияДокумента.Оперативный, Неопределено, Новый Граница(МоментВремени(),ВидГраницы.Исключая));
Запрос.УстановитьПараметр("ТочкаИтогов",ТочкаИтогов);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Движение = Движения.Взаиморасчеты.ДобавитьПриход();
Движение.Период = Дата;
Движение.Счет = Выборка.Счет;
Движение.Контрагент = Выборка.Контрагент;
Движение.Сумма = Выборка.Долг * Выборка.ДнейПросрочки *(Выборка.ПроцентПени/100);
КонецЦикла;
КонецПроцедуры
7) Отчет "Анализ состояния счетов"
Текст запроса:
ВЫБРАТЬ
СчетаОстаткиИОбороты.Счет,
МАКСИМУМ(СчетаОстаткиИОбороты.Регистратор.Дата) КАК РегистраторДата
ПОМЕСТИТЬ ОтгруженныеСчета
ИЗ
РегистрНакопления.Счета.ОстаткиИОбороты(, &Период, Регистратор, , ) КАК СчетаОстаткиИОбороты
ГДЕ
СчетаОстаткиИОбороты.СуммаКонечныйОстаток = 0
СГРУППИРОВАТЬ ПО
СчетаОстаткиИОбороты.Счет
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
СчетаОстатки.Счет
ПОМЕСТИТЬ НеотгруженныеСчета
ИЗ
РегистрНакопления.Счета.Остатки(&Период, ) КАК СчетаОстатки
ГДЕ
СчетаОстатки.СуммаОстаток > 0
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВзаиморасчетыОстатки.Счет,
ОтгруженныеСчета.РегистраторДата КАК ДатаПолнойОтгрузки,
ВзаиморасчетыОстатки.СуммаОстаток КАК ЗадолженностьПоСчету
ИЗ
РегистрНакопления.Взаиморасчеты.Остатки(
&Период,
Счет В
(ВЫБРАТЬ
НеотгруженныеСчета.Счет КАК Счет
ИЗ
НеотгруженныеСчета КАК НеотгруженныеСчета)
ИЛИ Счет В
(ВЫБРАТЬ
ОтгруженныеСчета.Счет КАК Счет
ИЗ
ОтгруженныеСчета КАК ОтгруженныеСчета)) КАК ВзаиморасчетыОстатки
ЛЕВОЕ СОЕДИНЕНИЕ ОтгруженныеСчета КАК ОтгруженныеСчета
ПО ВзаиморасчетыОстатки.Счет = ОтгруженныеСчета.Счет
ГДЕ
ВзаиморасчетыОстатки.СуммаОстаток > 0
8) Отчет "Анализ счета за период"
ВЫБРАТЬ
ВзаиморасчетыОстаткиИОбороты.Регистратор КАК Документ,
ВзаиморасчетыОстаткиИОбороты.СуммаПриход КАК Задолженность,
ВзаиморасчетыОстаткиИОбороты.СуммаРасход КАК Оплачено
ИЗ
РегистрНакопления.Взаиморасчеты.ОстаткиИОбороты(&ДатаНачала, &ДатаОкончания, Регистратор, ДвиженияИГраницыПериода, Счет = &Счет) КАК ВзаиморасчетыОстаткиИОбороты
УПОРЯДОЧИТЬ ПО
ВзаиморасчетыОстаткиИОбороты.Регистратор.Дата
1) Для решения потребуется 2 регистра накопления "Взаиморасчеты" и "Счета".
Структуры регистров:
Взаиморасчеты Измерения "Контрагент", "Счет" ресурс "Сумма".
Счета Измерения "Контрагент", ресурс "Сумма".
2) Документы "Расходная накладная " и 3 новых "Пени", "ПоступлениеДенег" и "Счет".
Документы будут делать движения по регистрам след. образом:
Счет ( Счет +)
Расходная накладная (Взаиморасчеты+ , Счета-)
Поступление денег "Взаиморасчеты-)
Пени(Взаиморасчеты+)
3) Документ "Счет"
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Движения.Счета.Записывать = Истина;
Движение = Движения.Счета.ДобавитьПриход();
Движение.Период = Дата;
Движение.Счет = Ссылка;
Движение.Сумма = Сумма;
КонецПроцедуры
4) Документ "Расходная накладная"
Чтобы документ вводился только на основании счета потребуется 2 процедуры
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
Если ДанныеЗаполнения = Неопределено Тогда
Отказ = Истина;
Сообщение = Новый("СообщениеПользователю");
Сообщение.Текст = "Документ можно вводить только на основании счета";
Сообщение.Сообщить();
Иначе
Счет = ДанныеЗаполнения;
Контрагент = ДанныеЗаполнения.Контрагент;
Дата = ТекущаяДата();
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Если Не ЗначениеЗаполнено(Объект.Счет) Тогда
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Обработка проведения:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Движения.Счета.Записывать = Истина;
Движения.Взаиморасчеты.Записывать = Истина;
// Блокировка
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.Счета");
ЭлементБлокировки.УстановитьЗначение("Счет", Счет);
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
Блокировка.Заблокировать();
Запрос = Новый("Запрос");
Запрос.Текст ="ВЫБРАТЬ
| СчетаОстатки.СуммаОстаток КАК Долг
|ИЗ
| РегистрНакопления.Счета.Остатки(&ТочкаИтогов, Счет = &Счет) КАК СчетаОстатки";
Запрос.УстановитьПараметр("Счет",Счет);
ТочкаИтогов = ?(РежимПроведения= РежимПроведенияДокумента.Оперативный, Неопределено, Новый Граница(МоментВремени(),ВидГраницы.Исключая));
Запрос.УстановитьПараметр("ТочкаИтогов",ТочкаИтогов);
Результат = Запрос.Выполнить();
Если Не Результат.Пустой() Тогда
Выборка = Результат.Выбрать();
Выборка.Следующий();
Если Выборка.Долг < СуммаПоДокументу Тогда
Отказ = Истина;
Сообщение = Новый("СообщениеПользователю");
Сообщение.Текст = "Сумма документа превышает сумму долга "+ Выборка.Долг;
Сообщение.Сообщить();
КонецЕсли;
КонецЕсли;
Если Не Отказ Тогда
Движение = Движения.Счета.ДобавитьРасход();
Движение.Период = Дата;
Движение.Счет = Счет;
Движение.Сумма = СуммаПоДокументу;
Движение = Движения.Взаиморасчеты.ДобавитьПриход();
Движение.Период = Дата;
Движение.Счет = Счет;
Движение.Сумма = СуммаПоДокументу;
Движение.Контрагент = Контрагент;
КонецЕсли;
КонецПроцедуры
5) Документ "Поступление денег"
Процедура ОбработкаПроведения(Отказ, Режим)
Движения.Взаиморасчеты.Записывать = Истина;
Движения.Взаиморасчеты.Записать() ;
// Блокировка
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.Взаиморасчеты");
ЭлементБлокировки.УстановитьЗначение("Контрагент", Контрагент);
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
Блокировка.Заблокировать();
Запрос = Новый("Запрос");
Запрос.Текст = "ВЫБРАТЬ
| ВзаиморасчетыОстатки.Счет,
| ВзаиморасчетыОстатки.СуммаОстаток КАК Долг
|ИЗ
| РегистрНакопления.Взаиморасчеты.Остатки(&ТочкаИтогов, Контрагент = &Контрагент) КАК ВзаиморасчетыОстатки
|
|УПОРЯДОЧИТЬ ПО
| ВзаиморасчетыОстатки.Счет.Дата
|ИТОГИ
| СУММА(Долг)
|ПО
| ОБЩИЕ";
Запрос.УстановитьПараметр("Контрагент",Контрагент);
ТочкаИтогов = ?(Режим= РежимПроведенияДокумента.Оперативный, Неопределено, Новый Граница(МоментВремени(),ВидГраницы.Исключая));
Запрос.УстановитьПараметр("ТочкаИтогов",ТочкаИтогов);
ВыборкаИтоги = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам,"Общие");
ВыборкаИтоги.Следующий();
Если ВыборкаИтоги.Долг < Сумма Тогда
Отказ = Истина;
Сообщение = Новый("СообщениеПользователю");
Сообщение.Текст = "Сумма документа превышает сумму долга "+ ВыборкаИтоги.Долг;
Сообщение.Сообщить();
Иначе
ОсталосьСписать = Сумма;
Выборка = ВыборкаИтоги.Выбрать();
Пока Выборка.Следующий() и ОсталосьСписать >0 Цикл
СуммаКСписанию = Мин(ОсталосьСписать, Выборка.Долг);
Движение = Движения.Взаиморасчеты.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Период = Дата;
Движение.Контрагент = Контрагент;
Движение.Счет = Выборка.Счет;
Движение.Сумма = СуммаКСписанию;
ОсталосьСписать = ОсталосьСписать - СуммаКСписанию;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
6) Документ "Пени"
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Движения.Взаиморасчеты.Записывать = Истина;
Движения.Взаиморасчеты.Записать() ;
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.Взаиморасчеты");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.Счета");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
Блокировка.Заблокировать();
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| СчетаОстаткиИОбороты.Счет,
| СчетаОстаткиИОбороты.СуммаКонечныйОстаток,
| МАКСИМУМ(СчетаОстаткиИОбороты.Регистратор.Дата) КАК ДатаПолнойОтгрузки
|ПОМЕСТИТЬ Счета
|ИЗ
| РегистрНакопления.Счета.ОстаткиИОбороты(, &ТочкаИтогов, Регистратор, , ) КАК СчетаОстаткиИОбороты
|ГДЕ
| СчетаОстаткиИОбороты.СуммаКонечныйОстаток = 0
|
|СГРУППИРОВАТЬ ПО
| СчетаОстаткиИОбороты.Счет,
| СчетаОстаткиИОбороты.СуммаКонечныйОстаток
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Счета.Счет,
| ЕСТЬNULL(ВзаиморасчетыОстатки.СуммаОстаток, 0) КАК Долг,
| Счета.Счет.ПроцентПени КАК ПроцентПени,
| ВзаиморасчетыОстатки.Контрагент,
| РАЗНОСТЬДАТ(Счета.ДатаПолнойОтгрузки, &Дата, ДЕНЬ) КАК ДнейПросрочки
|ИЗ
| РегистрНакопления.Взаиморасчеты.Остатки(
| &ТочкаИтогов,
| Счет В
| (ВЫБРАТЬ
| Счета.Счет
| ИЗ
| Счета)) КАК ВзаиморасчетыОстатки
| ЛЕВОЕ СОЕДИНЕНИЕ Счета КАК Счета
| ПО ВзаиморасчетыОстатки.Счет = Счета.Счет";
Запрос.УстановитьПараметр("Дата", Дата);
ТочкаИтогов = ?(РежимПроведения= РежимПроведенияДокумента.Оперативный, Неопределено, Новый Граница(МоментВремени(),ВидГраницы.Исключая));
Запрос.УстановитьПараметр("ТочкаИтогов",ТочкаИтогов);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Движение = Движения.Взаиморасчеты.ДобавитьПриход();
Движение.Период = Дата;
Движение.Счет = Выборка.Счет;
Движение.Контрагент = Выборка.Контрагент;
Движение.Сумма = Выборка.Долг * Выборка.ДнейПросрочки *(Выборка.ПроцентПени/100);
КонецЦикла;
КонецПроцедуры
Текст запроса:
ВЫБРАТЬ
СчетаОстаткиИОбороты.Счет,
МАКСИМУМ(СчетаОстаткиИОбороты.Регистратор.Дата) КАК РегистраторДата
ПОМЕСТИТЬ ОтгруженныеСчета
ИЗ
РегистрНакопления.Счета.ОстаткиИОбороты(, &Период, Регистратор, , ) КАК СчетаОстаткиИОбороты
ГДЕ
СчетаОстаткиИОбороты.СуммаКонечныйОстаток = 0
СГРУППИРОВАТЬ ПО
СчетаОстаткиИОбороты.Счет
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
СчетаОстатки.Счет
ПОМЕСТИТЬ НеотгруженныеСчета
ИЗ
РегистрНакопления.Счета.Остатки(&Период, ) КАК СчетаОстатки
ГДЕ
СчетаОстатки.СуммаОстаток > 0
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВзаиморасчетыОстатки.Счет,
ОтгруженныеСчета.РегистраторДата КАК ДатаПолнойОтгрузки,
ВзаиморасчетыОстатки.СуммаОстаток КАК ЗадолженностьПоСчету
ИЗ
РегистрНакопления.Взаиморасчеты.Остатки(
&Период,
Счет В
(ВЫБРАТЬ
НеотгруженныеСчета.Счет КАК Счет
ИЗ
НеотгруженныеСчета КАК НеотгруженныеСчета)
ИЛИ Счет В
(ВЫБРАТЬ
ОтгруженныеСчета.Счет КАК Счет
ИЗ
ОтгруженныеСчета КАК ОтгруженныеСчета)) КАК ВзаиморасчетыОстатки
ЛЕВОЕ СОЕДИНЕНИЕ ОтгруженныеСчета КАК ОтгруженныеСчета
ПО ВзаиморасчетыОстатки.Счет = ОтгруженныеСчета.Счет
ГДЕ
ВзаиморасчетыОстатки.СуммаОстаток > 0
8) Отчет "Анализ счета за период"
ВЫБРАТЬ
ВзаиморасчетыОстаткиИОбороты.Регистратор КАК Документ,
ВзаиморасчетыОстаткиИОбороты.СуммаПриход КАК Задолженность,
ВзаиморасчетыОстаткиИОбороты.СуммаРасход КАК Оплачено
ИЗ
РегистрНакопления.Взаиморасчеты.ОстаткиИОбороты(&ДатаНачала, &ДатаОкончания, Регистратор, ДвиженияИГраницыПериода, Счет = &Счет) КАК ВзаиморасчетыОстаткиИОбороты
УПОРЯДОЧИТЬ ПО
ВзаиморасчетыОстаткиИОбороты.Регистратор.Дата
Комментариев нет:
Отправить комментарий