|
23.12.2008, 17:46 | #1 |
Участник
|
Как передать параметр из Job-a в Class с возможностью перезаписи?
Всем доброго времени суток!
У меня такая проблема: Я запускаю сценарий (Job) из класса. Но передать значение переменной (даже при использовании системных классов) после первого "захода" в Job не получается. Предыдущее значение не перезаписывается. Вариант временно хранить в таблице не подходит. Требование Клиента. Уважаемые коллеги, подскажите, как мне решить эту проблему. Исходные данные: Job: X++: static AmountMST ScenarioScript134218100335() { /////////////////////////////////////// Системное объявление переменных. Не редактировать! --> Date startDate; // Начальная дата для пересчета сценария Date endDate; // Конечная дата для пересчета сценария AmountMST reslt; // Промежуточный результат пересчета сценария JobName jobName; // Название сценария \Data Dictionary\Extended Data Types\JobName LedgerRRGOperationTable_RU ledgerRRGOperationTable; // Запись таблицы "Оперции над ячейкой отчета" LedgerRRGCellTable_RU ledgerRRGCellTable; // Запись таблицы "Ячейки отчетов" LedgerPeriodCode ledgerPeriodCode; // Запись таблицы "Интервалы дат" RefRecId RRecId; // RecId записи таблицы "Оперции над ячейкой отчета" job jb = new Job(); // Экземпляр сценария JobName rr; // Значение RecId AmountMST result; // Промежуточный результат пересчета сценария AmountMST relt; // Результат пересчета сценария /////////////////////////////////////// Системное объявление переменных. Не редактировать! <-- // USER VARIABLES --> CustTable ct; CustTrans ctr; VendTable vt; VendTrans vtr; AmountMst Amount; // USER VARIABLES <-- ; ////////////////////////////////////// Системная инициализация переменных. Не редактировать! --> jobName = funcname(); // Выбор записи таблицы "Оперции над ячейкой отчета" ttsbegin; select firstonly forupdate ledgerRRGOperationTable where ledgerRRGOperationTable.CIT_JobName == jobName; // Выбор записи таблицы "Ячейки отчетов" select firstonly forupdate ledgerRRGCellTable where ledgerRRGCellTable.RecId == ledgerRRGOperationTable.CellRecId; // Если в записи таблицы "Оперции над ячейкой отчета" определен интервал дат из таблицы "Интервалы дат" if(ledgerRRGOperationTable.LedgerPeriodCode) { select firstonly forupdate ledgerPeriodCode where ledgerPeriodCode.Code == ledgerRRGOperationTable.LedgerPeriodCode; startDate = ledgerPeriodCode.StartFixedDate; endDate = ledgerPeriodCode.EndFixedDate; } else { // В противном случае определяем интервал дат из таблиц "Ячейки отчетов" и "Интервалы дат" select firstonly forupdate ledgerPeriodCode where ledgerPeriodCode.Code == ledgerRRGCellTable.LedgerPeriodCode; startDate = ledgerPeriodCode.StartFixedDate; endDate = ledgerPeriodCode.EndFixedDate; } rr = substr(jobName,23,10); // Определение значения RecId записи таблицы "Оперции над ячейкой отчета" RRecId = str2int64(rr); ////////////////////////////////////// Системная инициализация переменных. Не редактировать! <-- // USER CODE --> Amount=0; while select * from ct WHERE ct.CustGROUP == "UPS" || ct.CustGROUP == "REGION" { select sum(AmountMst) from ctr WHERE ctr.ACCOUNTNUM ==ct.ACCOUNTNUM && (ctr.TRANSDATE >=startdate && ctr.transDATE<= endDATE); IF (ctr.AmountMst < 0) AMOUNT+=ABS(ctr.AmountMst ); } while select * from vt WHERE vt .VendGroup == "PUMA" || vt .VendGroup == "SERIAL" { select sum(amountMst) from vtr WHERE vtr.AccountNum == vt.ACCOUNTNUM && (vtr.TRANSDATE >=startdate && vtr.transDATE<= endDATE); IF (vtr.AmountMst < 0) AMOUNT+=ABS(vtr.AmountMst ); } relt=amount; // USER CODE <-- //////////////////////////////// Присвоение значения результата пересчета сценария. Не редактировать! --> ledgerRRGOperationTable.CIT_Result = relt; // \Data Dictionary\Tables\LedgerRRGOperationTable_RU\Fields\ Result добавленное поле где мы временно храним значение переменной ledgerRRGOperationTable.update(); appl.parmResssy(relt); // Здесь проблемное место. Передаем значение переменной во вновь созданный метод \Classes\Application\parmResssy для \Classes\Application\classDeclaration: AmountMST resssy; ttscommit; //////////////////////////////// Присвоение значения результата пересчета сценария. Не редактировать! <-- return relt; } \Classes\LedgerRRGRunReport_RU\CIT_ScenarioScriptVend: X++: protected AmountMST CIT_ScenarioScriptVend(LedgerRRGAccountNumMap_RU _ScenarioAccountNumMap, // Таблица настроек Генератора DateCode _ScenarioDateCode, // Скрипт сценария (Не нужно) CIT_JobName _JobName, // Название job-а FreeTxt _ScenarioFreeTxt) // Скрипт сценария (Не нужно) { #AOT AmountMST resultVend; AmountMST ressst; job j= new Job(); str jobName; // Название job-а LedgerRRGOperationTable_RU ledgerRRGOperationTable; // Таблица настроек Генератора ; jobName = _JobName; j = TreeNode::findNode(#JobsPath + "\\" + JobName); if(j) j.AOTrun(); resultVend = appl.parmResssy(); // Проблемное место. Не перезаписывается значение переменной. return resultVend; } \Classes\Application\parmResssy: X++: public AmountMST parmResssy(AmountMST _resssy = resssy) { ; resssy = _resssy; return resssy; } |
|
23.12.2008, 17:49 | #2 |
Axapta
|
Сделайте вместо Джоба нормальный Класс, потомок RunBase. Джобы используются для неких разовых операций и не участвуют в бизнес-логике.
|
|
23.12.2008, 17:56 | #3 |
Участник
|
Сценарий нужен для доработки Генератора финансовых отчетов.
Из формы настроек конструктором я генерю Job-ы. При этом Клиент имеет возможность дорабатывать сам сценарий в форме. А дальше по настройкам формируются отчеты. Классы генерить конструктором не правильно. Дляэтого есть соответствующая ветка сценариев - \Jobs |
|
23.12.2008, 19:58 | #4 |
Участник
|
Цитата:
Конструкторы штатные, например, конфигуратор или мастер создания налогового регистра, формируют именно классы. |
|
23.12.2008, 22:20 | #5 |
Administrator
|
Цитата:
Пусть генерится класс. А чем плох класс? Чем джоб лучше класса? Тем что он лучше виден в АОТе и его легче прибить? Ну так сделайте у классов некоторый префикс и пусть его будет также легко и непринужденно прибить как джоб. Можно дальше пойти. Можно создать проект, в который добавлять программно классы, созданные из кода. Тогда эти классы будет прибить еще легче чем джобы.
__________________
Возможно сделать все. Вопрос времени |
|
24.12.2008, 07:16 | #6 |
Участник
|
Цитата:
Вот и извращается. |
|
23.12.2008, 17:52 | #7 |
Участник
|
OMG
X++: jobName = _JobName; j = TreeNode::findNode(#JobsPath + "\\" + JobName); if(j) j.AOTrun(); |
|
23.12.2008, 18:18 | #8 |
Боец
|
Можно пользовать, например, GlobalCache, передавать\забирать параметры через него.
infolog.globalCache().set infolog.globalCache().get Кстати с системными классами тож должно работать... попробуйте info вместо application. |
|
|
За это сообщение автора поблагодарили: Yury J (1). |
23.12.2008, 19:28 | #9 |
Участник
|
Еще про кэширование:
http://erpkb.com/Axapta/Singleton
__________________
AxAssist 2012 - Productivity Tool for Dynamics AX 2012/2009/4.0/3.0 |
|
24.12.2008, 07:22 | #10 |
Участник
|
Цитата:
Обратите внимание, что все job'ы имеют аргументы Args _args. Через них родимых и надо передавать, если уж твердо решили делать через job'ы. Т.е. вы должны объявить X++: static AmountMST ScenarioScript134218100335(Args _args) |
|
24.12.2008, 09:28 | #11 |
Участник
|
Доброго времени суток.
Спасибо большое всем за оперативную помощь! Проблему решил воспользовавшись помощью DSPIC: Можно пользовать, например, GlobalCache, передавать\забирать параметры через него. infolog.globalCache().set infolog.globalCache().get Мой тебе, DSPIC респект! Тему можно закрывать. Постараюсь по максимуму ответить на ваши вопросы Михаил Андреев Это где Вы такое прочитали или сами придумали? Конструкторы штатные, например, конфигуратор или мастер создания налогового регистра, формируют именно классы. Я создал свой класс конструктор в 4-ке, который при помощи xppCompiler, freeTxt,treenode,job X++: t = infolog.findNode("Jobs");
j = t.AOTfindChild(jobName); Для пользователя добавил вставочку где он может объявлять объекты и переменные. А также вставочку где он рисовал свой ко логики. Сам Job вывается по кнопочке из строк настроек Генератора финансовых ротчетов. Для этого добавлен тип строки "Сценарий". как в конкорде. Вот и все. Таким инструментом пользователь может строить любую отчетность. Пример был разобран мною выше по коду Jb-а. sukhanchik Цитата:
Вообще-то основное правило в Аксапте - посмотри как это уже сделали до тебя и сделай по аналогии. Это я к тому, что все вставки на X++ (например при импорте данных) хранятся в таблице в контейнере. Конечно - код приложения в таблице хранить - это та еще засада, но модифицировать только ради этого класс Application я считаю тоже излишне.
Пусть генерится класс. А чем плох класс? Чем джоб лучше класса? Тем что он лучше виден в АОТе и его легче прибить? Ну так сделайте у классов некоторый префикс и пусть его будет также легко и непринужденно прибить как джоб. Можно дальше пойти. Можно создать проект, в который добавлять программно классы, созданные из кода. Тогда эти классы будет прибить еще легче чем джобы. Но для работы нужен был именно этот вариант решения. Таковы были требования Клиента. А Клиент, сам понимаешь, всегда прав. И работа уже выполнена и сдана. Но только промежуточное значение? как ты и пишешь храyилось в таблице. Что не есть правильно. И при высокой плотности обращений падала производительность построения отчета. Кроме прочего отчет еще выводится в Excel. mazzy X++: AOT - , main . . Вспомните модуль GALAXY. И Вам много станет понятно. Или Датчане тоже извращенцы? mazzy PHP код:
Я всё это знаю. Но я пошёл свом путём . |
|
24.12.2008, 09:33 | #12 |
Участник
|
Внизу каждого сообщения есть ссылка "Поблагодарить автора сообщения".
Нажмите и ваш респект отобразится в его профиле. Пока респект только на словах Цитата:
Ок. Цезарь, идущие на смерть приветствуют тебя! (С) |
|
24.12.2008, 14:06 | #13 |
Administrator
|
Цитата:
Сообщение от Yury J
Но для работы нужен был именно этот вариант решения. Таковы были требования Клиента.
А Клиент, сам понимаешь, всегда прав. И работа уже выполнена и сдана. Но только промежуточное значение? как ты и пишешь храyилось в таблице. Что не есть правильно. И при высокой плотности обращений падала производительность построения отчета. Кроме прочего отчет еще выводится в Excel. Я говорю о том, что изначальное решение - формировать джобы - неверное. Не нужно было с ними изначально связываться. Таково мое мнение. А вот в отношении правоты Клиента готов поспорить. Конечно, при уже оттестированном коде, который генерит джобы - ломать все - не есть правильно. С одной стороны. С другой стороны, если этот функционал будет еще активно развиваться - то лучше сразу его сломать. Работал я по принципу - Клиент всегда прав. Оказалось - что Клиент-то на самом деле не всегда прав. Если исключить откровенную дурость - то всегда можно прийти к консенсусу, который выродится в минимальное кол-во изменений. В противном случае - работа выльется в то, что придется туда-сюда переделывать, а Клиент будет недоволен - что никак все не сделаете. А в случае откровенной дурости - надо танцевать от позиции "В Аксапте это невозможно". Это хорошо действует, даже если это технически возможно. В общем-то "Жираф большой ему видней" - так что если Вы решили свои задачи - значит для Вас все ок.
__________________
Возможно сделать все. Вопрос времени |
|
|
За это сообщение автора поблагодарили: oip (1). |
24.12.2008, 14:08 | #14 |
Axapta
|
Цитата:
Оффтоп: Аналогично, когда программист читает ТЗ, то тоже не надо считать, что "консультант всегда прав, поэтому раз так написано в задании, то надо делать именно так." А то часто тут на форуме проскакивает "это не моя вина, мне так написали в ТЗ". Если в ТЗ написано не так, как надо, необходимо сказать об этом постановщику и найти компромис. Upd. http://www.amand.ru/modules/wordpres...ves/67#more-67 |
|
|
За это сообщение автора поблагодарили: Logger (4). |
11.01.2009, 17:11 | #15 |
Участник
|
Цитата:
Сообщение от oip
Я обычно говорю "в Аксапте это сделать очень трудоемко" и говорю свою временную оценку (несколько завышенную) и о последствиях предупреждаю, чтобы уж не сильно обманывать. Действует. И всех учу не работать слепо по принципу "клиент всегда прав". Клиент НЕ всегда прав. А так полностью согласен. Более того, я не верю, что у клиента было требование сделать именно джоб. Думаю, клиенту надо чтобы работало. А уж как это будет сделано - не его забота.
Оффтоп: Аналогично, когда программист читает ТЗ, то тоже не надо считать, что "консультант всегда прав, поэтому раз так написано в задании, то надо делать именно так." А то часто тут на форуме проскакивает "это не моя вина, мне так написали в ТЗ". Если в ТЗ написано не так, как надо, необходимо сказать об этом постановщику и найти компромис. Upd. http://www.amand.ru/modules/wordpres...ves/67#more-67 Все правильно, но, к сожалению, разработчик не всегда имеет соответствующий вес, чтобы так говорить. |
|