AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 19.06.2015, 12:46   #1  
syl is offline
syl
Участник
Аватар для syl
 
236 / 21 (1) +++
Регистрация: 10.06.2015
Адрес: Киев
Определение используемых полей
Доброго времени суток!

Пытаюсь разобраться в тонкостях системы ax 2009, стоит задача определить какие поля из каких таблиц и при каких параметрах выводятся в отчет.

Отчет company->Расчеты с поставщиками->Запросы->Оборотно-сальдовая ведомость

Определил что всю работу делает класс RLedgerSheetEngine унаследованный от RunBase. В его методе query формируется запрос который использует лишь одну таблицу - LedgerTrans. (Хотя дебагер говорит что данный метод не используется).

В общем помогите разобраться с вопросом, я в AX новичок, подскажите с чего нужно начинать поиск при подобных задачах, ведь запросы могут строится не только в коде. В общем буду признателен любой информации по данному вопросу, ато я уже себе голову сломал и ничего найти не смог...
Старый 19.06.2015, 13:09   #2  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,940 / 3229 (115) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Полагаю в ошиблись в изысканиях.
Там есть 3 класса наследника - для расчетов с поставщиками (табличка VendTrans)
для расчетов с клиентами (табличка custTrans)
для главной книги (табличка LedgerTrans)

Если вы действительно смотрите Отчет company->Расчеты с поставщиками->Запросы->Оборотно-сальдовая ведомость
то смотрите наследник обрабатывающий vendTrans
Старый 19.06.2015, 13:24   #3  
syl is offline
syl
Участник
Аватар для syl
 
236 / 21 (1) +++
Регистрация: 10.06.2015
Адрес: Киев
Logger, я с вами полностью согласен. В данном случае наследник LedgerSheetEngine_TurnoverVend, тут используется одна таблица - VendTrans, но по идее поля в отчете берутся не только из нее, я не могу понять где они выбираются. Еще в диалоге есть комбобокс custVendDetailBalans, в зависимости от его значения отчет ведет себя по разному и показывает разные столбцы - этого в коде я тоже пока не смог найти.
Старый 19.06.2015, 13:26   #4  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,940 / 3229 (115) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Попробуйте выбрать простой случай когда обрабатывается 1-2 проводки.
И пройдитесь с отладчиком по шагам.
За это сообщение автора поблагодарили: syl (1).
Старый 19.06.2015, 14:04   #5  
syl is offline
syl
Участник
Аватар для syl
 
236 / 21 (1) +++
Регистрация: 10.06.2015
Адрес: Киев
Прошел.

Запрос так и не обнаружил, но выяснил что данные добавляются построчно и берутся они из turnoverIterator = new MapIterator(mapData);

mapData: mapData = rLedgerSheetServerCV.getMap();

rLedgerSheetServerCV: не понятно от куда берется...
Старый 19.06.2015, 14:35   #6  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,691 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Общая логика работы всех оборотно-сальдовых ведомостей в Ax2009 выглядит примерно так

К пункту меню привязана форма RLedgerSheet

В событии init формы RLedgerSheet создается экземпляр класса наследника от RLedgerSheetEngine, который открывает диалог с пользователем для установки ряда настроек и фильтров для последующего расчета.

После установки настроек пользователем, если была нажата кнопка «Ок», то выполняется ряд расчетов в этом же классе. А, кроме того, создается и запускается экземпляр класса наследника от RLedgerSheetServer, который формирует и хранит список записей по документам-источникам и суммовые показатели по этим документам.

X++:
// init формы RLedgerSheet 

// Создается класс-наследник от RLedgerSheetEngine
rLedgerSheetEngine = RLedgerSheetEngine::construct(element.args());

super();

// Диалог с пользователем
if (! rLedgerSheetEngine.prompt())
{
   // Если нажади "Отмена", то закрываем форму
    this.close();
    return;
}

// Передаем в класс ссылку на объект ListView на форме
rLedgerSheetEngine.parmFormListControl(turnoverAmount);

// Собственно выполнение расчета
rLedgerSheetEngine.run();
Метод construct() вызывает метод new(), в котором выполняется

X++:
    this.initFieldsData();
    this.initValuesData();
this.initFieldsData() - это ручное наполнение filedMap – список полей для промежуточных итогов и сортировки. Это набор формируемый из левого списка в диалоге с пользователем

this.initValuesData() – это метод, в котором можно инициализировать переменные. Как правило, не используется. Предполагается, что по умолчанию все переменные пустые, а пользователь их заполняет, если необходимо

Метод run() перекрыт в классе наследнике RLedgerSheetClient. Если убрать «обвязку», то имеем следующее

X++:
this.initAccounts();			// Инициализация

this.createRLedgerSheetServer();		// Создание экземпляра класса RLedgerSheetServer для расчета
this.executeRLedgerSheetServer();	// Собственно расчет

this.getDataFromServer();		// перекачка данных из расчетного класса в текущий

this.initListView();			// Формирование столбцов объекта формы ListView
this.fetchNextRows();			// Заполнение строк объекта формы ListView
this.setItem();				// включение/выключение ряда объектов и установка фокуса
Если объединить методы this.createRLedgerSheetServer() и this.executeRLedgerSheetServer(), то получим примерно такой код

X++:
    rLedgerSheetServer =  RLedgerSheetServer::construct(this.parmRLedgerSheetType());
    rLedgerSheetServer.initParameters(this.queryRun(), this.getParmContainer());
    rLedgerSheetServer.run(this.initRunQuery());
rLedgerSheetType – это Base Enum, значение которого передается через args.parmEnum() в методе
this.queryRun() – настроенный пользователем QueryRun
this.initRunQuery() – если не перекрыт, то queryRun.query()

RLedgerSheetEngine::Construct(args). Определяет, какие именно классы-наследники от RLedgerSheetEngine и RLedgerSheetServer будут созданы.
this.getParmContainer() – контейнер, содержащий список переменных с настройками пользователя

X++:
return [ currencyType,		//Тип валюты, в которой выполнять расчет (основная, вторичная, указанная)
         deleteZero,		//Из диапазона расчета исключить даты, не имеющие ни одной заявки на оплату
         showSumAccount,		//Отображать строки с итоговыми суммами
         dimensionCriteria,	//Финансовые аналитики
         fromDate,		//Начальная дата диапазона
         toDate,			//Конечная дата диапазона
         operationsTax,		//По какому уровню рассчитывать бухгалтерское сальдо (Base Enum)
         currencyCode,		//Код валюты, в которой выполнять расчет, если currencyType = указанная
         selectedFieldsOrder	//Выбранные поля сортировки (поставщик, договор, счет ГК)
         ];
__________________
- Может, я как-то неправильно живу?!
- Отчего же? Правильно. Только зря...
За это сообщение автора поблагодарили: Ruff (5).
Старый 19.06.2015, 14:39   #7  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,691 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от syl Посмотреть сообщение
Прошел.

Запрос так и не обнаружил, но выяснил что данные добавляются построчно и берутся они из turnoverIterator = new MapIterator(mapData);

mapData: mapData = rLedgerSheetServerCV.getMap();

rLedgerSheetServerCV: не понятно от куда берется...

Посмотрите начало метода getDataFromServer(), где выполняется определение переменных

X++:
protected void getDataFromServer()
{
    RLedgerSheetServer_TurnoverCustVend rLedgerSheetServerCV = rLedgerSheetServer;

(...)

Т.е. rLedgerSheetServerCV - это просто "перименование" ранее созданного объекта rLedgerSheetServer. Смысл такого "переименования" в том, что в переменной rLedgerSheetServer записана ссылка на экземпляр базового класса RLedgerSheetServer. А "переименование" записывает в переменную rLedgerSheetServerCV уже экземпляр класса-наследника RLedgerSheetServer_TurnoverCustVend
__________________
- Может, я как-то неправильно живу?!
- Отчего же? Правильно. Только зря...

Последний раз редактировалось Владимир Максимов; 19.06.2015 в 14:45.
Старый 19.06.2015, 15:01   #8  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,691 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Да, собственно запрос - это метод rLedgerSheetEngine.query(), который вызывается при инициализации переменной queryRun в методе rLedgerSheetEngine.queryRun(). Естественно, для разных классов-наследников наполнение метода rLedgerSheetEngine.query() разное.

Для ОСВ по поставщику - это таблица vendTrans - Проводки по поставщику.
__________________
- Может, я как-то неправильно живу?!
- Отчего же? Правильно. Только зря...
За это сообщение автора поблагодарили: syl (1).
Старый 19.06.2015, 15:37   #9  
syl is offline
syl
Участник
Аватар для syl
 
236 / 21 (1) +++
Регистрация: 10.06.2015
Адрес: Киев
Я выявил такой запрос:

NAME:
qbds
VALUE: SELECT FIRSTFAST * FROM VendTrans WHERE ((TransDate<={ts '2014-12-31 00:00:00.000'})) AND ((Dimension[4] = N'GRUPPOTECN')) AND ((EmplAccount_RU = ' '))
TYPE: QueryBuildDataSource

Но я так и не понял где именно он формируется. Везде где в наследниках есть метод Query пытался дебажить, эти методы просто не вызываются. Я уже разобрал последовательность вызов и логику работы, но мне нужно найти где именно формируется запрос, и что он туда пихает и из каких таблиц. Либо дебагер перехватывает не все методы, либо я что то упустил...

X++:
//RLedgerSheetEngine.Run()
SysQueryRun     runQuery;
    ;

    this.initAccounts();
    runQuery = new SysQueryRun(this.initRunQuery());
    while(runQuery.next())
    {
        this.loopAction(runQuery);
    }

X++:
protected Query initRunQuery()
{
    return queryRun.query();
}
Где найти этот самый queryRun.query(), откуда он берет свое значение?

Последний раз редактировалось syl; 19.06.2015 в 16:04.
Старый 19.06.2015, 16:08   #10  
Ruff is offline
Ruff
Дмитрий Ерин
Аватар для Ruff
1C
 
475 / 396 (14) ++++++
Регистрация: 18.09.2003
Адрес: Тула
Запросы могут упаковываться/распаковываться (то есть хранить выбранные пользователем значения в промежутках между запусками). Смотрите методы pack(), unpack().
Старый 19.06.2015, 16:58   #11  
syl is offline
syl
Участник
Аватар для syl
 
236 / 21 (1) +++
Регистрация: 10.06.2015
Адрес: Киев
Цитата:
Сообщение от Ruff Посмотреть сообщение
Запросы могут упаковываться/распаковываться (то есть хранить выбранные пользователем значения в промежутках между запусками). Смотрите методы pack(), unpack().
А толку? Они то упаковываются, но увидеть что там внутри все равно нельзя. Никакой ясности это не вносит...

С самим запросом я походу разобрался, он формируется в методе query rLedgerSheetEngine_TurnoverVend, потом по ходу алгоритма на него накладываются фильтры.
Затем в методе loopBalanceTrans rLedgerSheetEngine_TurnoverCustVend происходит расчет, fetchNextRows построчно добавляет данные. Последнее что осталось определить какие поля выводятся на конечную форму...

Последний раз редактировалось syl; 19.06.2015 в 17:07.
Старый 20.06.2015, 15:20   #12  
Raven Melancholic is offline
Raven Melancholic
Участник
Аватар для Raven Melancholic
Самостоятельные клиенты AX
Лучший по профессии 2015
 
2,164 / 1293 (48) ++++++++
Регистрация: 21.03.2005
Адрес: Москва-Петушки
Вообще все данные по для получения сальдо/оборотов по поставщику, в основном, находятся в трех таблицах, это VendTrans, VendTransOpen и VendSettlement. Ну, за некоторыми данными нужно лезть в самого поставщика VendTable.
Дальше уже зависит от того, какая задача стоит.
Если нужно что-то изменить в ОСВ по поставщикам, то придется продираться через механизм ОСВ Российской локализации, про которую пишет Владимир Максимов. Если же этот отчет нужен только для того, чтобы понять как получить остатки и обороты по поставщикам, то лучше не нужно.
На мой взгляд, эта подситстема ОСВ в DAX является явным антипатерном - показывает как не нужно делать в DAX. Тут явно при локализации была задача от заказчика "сделайте как в 1С". Возможно, что задача и нужная, но её реализация кривая.
Если хотите просто узнать как получать данные по оборотам и остаткам (не исключено, что в связке с условиями оплаты), то смотрите стандартные отчеты:
  • Расчеты с поставщиками \ Отчеты \ Статус \ Оборотная ведомость поставщика
  • Расчеты с поставщиками \ Отчеты \ Статус \ Сальдовая ведомость с кредитными лимитами
ну и другие, в который нет суффикса _RU. Так же можно посмотреть стандартные отчеты, созданные не в X++, а для MS Reporting Services
Старый 20.06.2015, 18:03   #13  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,691 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от syl Посмотреть сообщение
Где найти этот самый queryRun.query(), откуда он берет свое значение?
Посмотрите здесь: Кнопка Выбрать в окне диалога.

QueryRun - это переменная, определенная в родительском классе RunBase. Она создается на основе переменной Query (которая формируется в rLedgerSheetEngine.query()) + все те настройки, которые может добавить пользователь, нажав кнопку "Выбрать".

Можно сказать так: query - настройки запроса по умолчанию при первом открытии диалога с пользователем, queryRun - реальные значения запроса, указанные пользователем в диалоге

PS: Российская локализация ОСВ сильно "покорежила" стандартную идеологию работы с классами-наследниками RunBase. Как обычно, впрочем... Почему-то российские локализаторы всегда идут "своим путем" даже не пытаясь понять идеологию Axapta.
__________________
- Может, я как-то неправильно живу?!
- Отчего же? Правильно. Только зря...
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Универсальный изменятель значений полей wojzeh DAX: Программирование 17 26.09.2013 17:47
axforum blogs: Определение термина ERP и требования к ERP-системам Blog bot DAX Blogs 0 07.03.2012 18:12
16 и более полей в InventDim Ievgenii DAX: Функционал 12 13.10.2011 13:56
Изменение идентификаторов(id) полей Dron AKA andy DAX: База знаний и проекты 30 17.06.2009 10:11
очистка полей. простой вопрос Антон Солдатов DAX: Программирование 4 04.04.2003 10:28
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 02:09.