Здравствуйте!
Т.к. такая задача видимо является часто встречаемой, хочу заранее спросить, чтобы не пойти по неправильному пути:
К примеру есть связка Продажы-Счета. Нужно в зависимости от Состояния оплаты Счета (Оплачен), просуммировать все счета Продажи и занести полученное значение в Продажу (колонка СуммаОплаченныхСчетов).
Создал функцию, которая считает сумму счетов по продаже и пишет в Продажу в колонку AmountPaid полученную сумму:
Dataset.Open();
...
SumAmount = SumAmount + Amount;
}
if (SumAmount!=Dataset.Values('AmountPaid')){
Dataset.Edit();
Dataset.Values('AmountPaid') = SumAmount;
Dataset.Post();
Dataset.Close();
}
InvoiceDataset.Close();
Подцепляю эту функцию на событие dlDataOnDatasetAfterOpen для wnd_OpportunityEditScript. Все работает, но я уверен, что такой подход в не совсем правильный, начиная от места расположения функции, заканчивая событием. Т.к. к примеру подсчет и запись происходит в момент открытия окна карточки Продажи. По правильному нужно, чтобы при изменении в Счете (Деталь Продаж) Состояния оплаты на Оплачен на это событие обновлялось значение "СуммаОплаченныхСчетов" в Продаже и визуально это сразу видно было бы в Гриде Продаж.
Подскажите как это реализовать правильно или может где есть хороший пример реализации такой связки?
Нравится
Я считаю, что правильно было бы вообще реализовать это уже в запросе, а не в датасете.
Скрины в приложении (по пунктам)
0) (Опасно, сделайте бекапы) Удалить все, что связано с этим полем (все скрипты с ним, удалить из карточки, грида, датасета, запроса, таблицы)
Или просто будем работать с другим именем поля. Например, PaidAmount.
1) Зайти в sq_Opportunities, добавить колонку подзапроса
2) Меняем имя колонки на нужное нам AmountPaid
3) В подзапросе выбираем таблицу tbl_invoice, называем ее как InvoicePaid
4) В select в подзапросе выбираем Amount или BasicAMount (смотря, что по душе. Я взял BasicAmount) и говорим, что нам нужна его сумма (ставим в поле итог Сумма)
5) Необходимо наложить фильтры
5.1) Фильтр связи продажи с счетом
В подзапросе в Where создать фильтр сравнения, назовем InvoicePaidOpportunityID
Слева в фильтре InvoicePaid.OpportunityID, справа Opportunity.ID
Включить его (не забыть поставить галочку)
5.2) Счета должны быть оплачены
В подзапросе присоединиям таблицу BillStatusID к таблице InvoicePaid
Назовем ее InvoicePaidBillStatus (Остальные параметры смотри на скриншоте 5_2_1)
В подзапросе в Where создать пользовательский SQL фильтр, назвать InvoicePaidBillStatusIsFinish, внизу объеденить с таблицей tbl_BillStatus AS InvociePaidBillStatus, в самом запросе написать 'InvoicePaidBillStatus.IsFinish = 1', не забыть включить фильтр
Все теперь сам запрос вычисляем нам это поле, теперь с ним можно работать как с обычным. Зайти в датасет добавить дробное поле, указать AmountPaid, лучше поставить ему свойство только для чтения, добавить в реестр, в карточку и т.д.
"Сазанов Александр Владимирович" написал:Я считаю, что правильно было бы вообще реализовать это уже в запросе, а не в датасете.
Скрины в приложении (по пунктам)
А не будет ли это очень долго считаться, когда колонка будет отображаться в grid'e?
Если делаете в конфигурации, то лучше всего создать специальный UpdateQuery сервис, который будет выполнять апдейт таблицы "Продажи" (в вашем случае), а затем выполнить его:
var myUQ = Services.GetNewItemByUSI('uq_UpdateOpportunitySumm'); SetParameterValue(myUQ.Parameters, 'OpportunityID', OpportunityID); SetPArameterValue(myUQ.Parameters, 'OpportunitySumm', Summ); myUQ.Execute();
Также перед этим, рекомендую еще и написать отдельный SelectQuery, который будет получать сумму по всем счетам продажи (чтобы не работать с датасетом, избежать циклов while и пр., иначе в будущем столкнотесь с проблемой быстродействия). Т.е. в SQ добавить одну колонку с агрегирующей функцией суммы по нужной колонке, и с фильтром сравнения по OpportunityID.
var mySQ = Services.GetNewItemByUSI('sq_GetInvoiceSumm'); SetParameterValue(mySQ.Parameters, 'OpportunityID', OpportunityID); var DS = sq.Open(); var InvoiceSumm = DS('InvoiceSumm'); DS.Close();
"Владимир Соколов" написал:А не будет ли это очень долго считаться, когда колонка будет отображаться в grid'e?
Когда отображаться не думаю, в гриде обычно по 40 записей на странице. По-моему Террасофт только их в запрос и берет. А вот когда в скрипте открываем весь датасет, то может быть.
Ну точно узнаем, если попросим Алекса замерить запросы с этим полем и без него.
"Alex GF" написал:Спасибо Александр! Работает! Ещё бы где-то рефреш добавить, чтобы в гриде сразу видно было обновление, а не после нажатия на кнопку обновить.
И ещё, где мы наш псевдомин в запросе AmountPaid привязываем к реальному столбцу в таблице?
В том-то и дело, что в таблице его нет, он вычисляется в запросе, поэтому не нужно никуда вешать никакие скрипты для его вычисления. А то пришлось бы вешать скрипты на Счета на AfterPost и BeforeDelete или AfterDelete