17.11.2020, 19:47 | #1 |
Участник
|
D365FO queryBuildDataSource.FindRange() не работает??
D365FO 10.0.12
Пишу RunBaseBatch. который делает автоматичские платежи по custTransOpen. где due date <= сегодня. Хотелось бы добавить возможность для пользователя выбрать вручную dueDate в фильтре запроса. Задумывалась такая логика: Изначально due date range очищается, Если пользователь выбирает вручную due date, то используем его. В данном случае пользователь выбрал неправильно- просто значение вместо диапазона: - due date == 2020-11-16 Если пользователь ничего не выбрал, автоматически добавляем диапазон: due date <= сегодня (2020-11-17) В реальности, пользователь выбрал значение вручную, но система все равно добавляет автоматический диапазон... Разве if(!qbds.findRange(fieldnum(CustTransOpen, dueDate))) не должен был увидеть уже имеющееся условие? X++: void run() { .... q = QueryRun.query(); /*в дебаггере: текущее значение имеет выбранный пользователем DueDate=2020-11-16: {SELECT MIN(dataAreaId), MIN(AccountNum), SUM(AmountCur) FROM CustTransOpen(CustTransOpen_1) GROUP BY CustTransOpen.AccountNum WHERE ((CustTransOpen(CustTransOpen_1).AccountNum = N'000000001')) AND ((CustTransOpen(CustTransOpen_1).DueDate = {ts '2020-11-16 00:00:00.000'}))} */ QueryBuildDataSource qbds = q.dataSourceTable(tableNum(CustTransOpen)); if(!qbds.findRange(fieldnum(CustTransOpen, dueDate))) { //несмотря на наличие DueDate range, дебаггер идет сюда и добавляется новый range qbds.addRange(fieldnum(CustTransOpen, dueDate)).value(queryRange(dateNull(), systemDateGet())); } Info(strFmt("Due date used: %1", qbds.rangeField(fieldnum(CustTransOpen, dueDate)).value())); /*в итоге получаем странный запрос с двумя разными фильтрами по due date: {SELECT MIN(dataAreaId), MIN(AccountNum), SUM(AmountCur) FROM CustTransOpen(CustTransOpen_1) GROUP BY CustTransOpen.AccountNum WHERE ((DueDate<={ts '2020-11-17 00:00:00.000'})) AND ((CustTransOpen(CustTransOpen_1).AccountNum = N'000000001')) AND ((CustTransOpen(CustTransOpen_1).DueDate = {ts '2020-11-16 00:00:00.000'}))} */ ..... } boolean unpack(container packedClass) { Integer locVersion = conPeek(packedClass,1); container locPackedQuery; switch (locVersion) { case #CurrentVersion: [locVersion,#CurrentList,locPackedQuery] = packedClass; break; default : return false; } if (locPackedQuery) { queryRun = new QueryRun(locPackedQuery); Query q = QueryRun.query(); QueryBuildDataSource qbds = q.dataSourceTable(tableNum(CustTransOpen)); if(qbds.findRange(fieldnum(CustTransOpen, dueDate))) { qbds.clearRange(fieldnum(CustTransOpen, dueDate)); } } else { return false; } return true; } |
|
17.11.2020, 20:48 | #2 |
Banned
|
Извините, что не по существу, а зачем вы вообще что-то программируете, когда появилось следующее:
https://docs.microsoft.com/en-us/dyn...yment-proposal |
|
17.11.2020, 21:02 | #3 |
Участник
|
Потому что платит не компания кому-то, а процессятся платежи от клиентов с использованием кредитных карт, данные о которых клиенты оставили компании.
|
|
17.11.2020, 21:30 | #4 |
Banned
|
Цитата:
|
|
17.11.2020, 21:59 | #5 |
Участник
|
есть набор требований и стандарный функционал для него не подходит:
1. платежи через кредитные карты 2, разные пеймент процессоры для разных карт в зависимости от месторасположения владельца карты 3. план платежей по датам с лимитом суммы 4. +установленный лимит по кредитной карте 5. возможность делать разные типы платежей по кредитной карте в зависимости от наличия авторизации и ее статуса 6. Вишенка - один батч который работает по всем хх+ имеющимся компаниям 7. Очень большие обьемы. никто вручную подтверждать ничего не будет - это физически невозможно. |
|
17.11.2020, 23:07 | #6 |
Banned
|
Понимаю.
По существу: Цитата:
Изначально due date range очищается
.findRange() возвращает объект, если он уже изначально прошит в Query (или не возвращает в противном случае, но обычно в таких задачах, как ваша, задается предопределенное условие). А значение его - строка - будет .findRange().value(). Оно может быть пустым или непустым. Почему бы вам не зафиксировать Range и не стирать просто его значение: X++: SysQuery::findOrCreateRange(qbds, fieldnum(CustTransOpen, dueDate)).value(SysQuery::emptyValue()) https://community.dynamics.com/ax/f/...agment-96834=1 Последний раз редактировалось EVGL; 17.11.2020 в 23:15. |
|
|
За это сообщение автора поблагодарили: alicedr (1). |
17.11.2020, 23:17 | #7 |
Участник
|
Спасибо за идею, добрый человек!!!
Задача вроде элементарная, а мудохаюсь уже несколько часов ((( Сейчас попробую. |
|
18.11.2020, 09:46 | #8 |
Участник
|
Есть универсальный способ находить заданные пользователем фильтры в то числе если пользователь задал фильтр по полю, изначально не прошитому в Query.
Данная функция возвращает значение фильтра по заданному Query, коду таблицы и коду поля в таблице.Если фильтр не найден или не задан, то возвращает пустую строку. X++: str getRangeValue(Query _query, TableId _tableId, FieldId _fieldId) { QueryBuildDataSource innerQbds; QueryBuildRange innerQbr; int idx; str ret; innerQbds = _query.dataSourceTable(_tableId); if (innerQbds && innerQbds.enabled()) { innerQbr = innerQbds.findRange(_fieldId); if (innerQbr && innerQbr.value()) { ret = innerQbr.value(); } else { for (idx = 1; idx <= _query.queryFilterCount(); idx++) { if (_query.queryFilter(idx).dataSource().name() == innerQbds.name() && _query.queryFilter(idx).value()) { ret = _query.queryFilter(idx).value(); break; } } } } return ret; } X++: getRangeValue(q, tableNum(CustTransOpen), fieldnum(CustTransOpen, dueDate));
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/ Последний раз редактировалось Ace of Database; 18.11.2020 в 09:52. |
|
|
За это сообщение автора поблагодарили: sukhanchik (6), alicedr (1). |
18.11.2020, 20:12 | #9 |
Участник
|
Ссылочка уже в избранных )))
Решение EVGL "железобетонной привязки" работает на ура. Спасибо огромное! |
|
21.11.2020, 04:04 | #10 |
Участник
|
|
|
21.11.2020, 07:28 | #11 |
Участник
|
Query и QueryBuildRange кстати с этих соображений тоже неправильно использовать, надо переходить на SysDa classes
X++: Therefore, use of the SysDa classes carries no overhead, unlike use of the QueryRun object, for example |
|
21.11.2020, 09:39 | #12 |
Участник
|
|
|
21.11.2020, 17:18 | #13 |
Administrator
|
Реабилитировали как-раз таки RunBase, который зачем-то "осквернили" в 2012. Но SysOperation-ом также можно пользоваться - просто он большей частью для SSRS-отчетов используется
__________________
Возможно сделать все. Вопрос времени |
|
|
|