06.05.2021, 10:01 | #1 |
Участник
|
О рукожо..ах (?). И немножко ER
В силу того что люди таки начали осваивать ER ( и довольно на удивление успешно, напоминая порой тетенек-бухгалтерш ака виртуозов Excel) приходится анализировать и их неудачи.
Одна из них оказалась связана с отчетом "Sales tax declaration info report for HU": Кто то талантливый из видимо в MS (в терминах одного самокритичного коллеги работавшего на данную контору - см заголовок) не стал как обычно выводить название в параметры или использовать константы, смог как то обойти кодревью, проверки и втиснуть шедевр в класс SalesTaxDeclarationInformationReportService который как понимаю таки венгерский отчет но без всяких суффиксов. Благодаря его столь решительному подходу попытки сделать свое в виде derive ов и прочего у консультантов обрекались на неудачу. X++: /// <summary> /// Called by service controller. /// </summary> /// <param name = "_dataContract">The report parameters.</param> [Microsoft.Dynamics.BusinessPlatform.SharedTypes.InternalUseOnlyAttribute] public void run(SalesTaxDeclarationInfoReportContract _dataContract) { dataContract = _dataContract; this.processReport(); this.runER(); } /// <summary> /// Called by service controller. /// </summary> private void runER() { ERIModelDefinitionParamsAction parameters = new ERModelDefinitionParamsUIActionComposite() .add( new ERModelDefinitionDatabaseContext() .addTemporaryTable(this.getTmpTaxReport())) .add( new ERModelDefinitionDatabaseContext() .addValue(tableNum(CompanyInfo), fieldNum(CompanyInfo, DataArea), curext())) .add( new ERModelDefinitionInputParametersAction() .addParameter('ParameterReportMode', dataContract.parmReportMode())) .add( new ERModelDefinitionInputParametersAction() .addParameter('model/ParameterFromDateRange',dataContract.parmTaxReportPeriodFromDate())) .add( new ERModelDefinitionInputParametersAction() .addParameter('model/ParameterToDateRange', dataContract.parmTaxReportPeriodToDate())); // Call ER to generate the report. ERFormatMappingTable eRFormatMappingTable; select RecId from eRFormatMappingTable where eRFormatMappingTable.Name == "Sales tax declaration info report for HU"; ERFormatMappingId formatMapping = eRFormatMappingTable.RecId; ERObjectsFactory::createFormatMappingRunByFormatMappingId(formatMapping) .withFileDestination(ERObjectsFactory::createFileDestinationBrowser()) .withParameter(parameters) .withCreatingObjectParameter(SalesTaxDeclarationInfoReportContract::parmERModelname(), classStr(SalesTaxDeclarationInfoReportContract), dataContract).run(); } |
|
06.05.2021, 10:18 | #2 |
Участник
|
Может, что-то типа этого?
X++: [ExtensionOf(classStr(SalesTaxDeclarationInformationReportService))] final class SalesTaxDeclarationInformationReportServiceNNN_Extension // <-- new extension { public void run(SalesTaxDeclarationInfoReportContract _dataContract) { try { throw Exception::Numeric; next run(_dataContract); } catch (Exception::Numeric) { dataContract = _dataContract; this.processReport(); this.nnnRunER(); // <- new method } } private void nnnRunER() { // ... } } |
|
|
За это сообщение автора поблагодарили: Ace of Database (3), axm2017 (4). |
06.05.2021, 10:33 | #3 |
Участник
|
Я бы порекомендовал завести нам багу.
Можно сделать свою копию (copy-on-write, как выражается fed). В качестве извратного нестабильного воркэраунда теоретически можно было бы подменять recID после загрузки записи, проанализировав коллстек на предмет вызова именно из этого класса. Еще можно у стандартного мепинга заменить имя на другое где-то (в xml файле или БД) а у кастомного сделать такое, как требует код. Но это теоретические возможности которые я не могу порекомендовать. |
|
|
За это сообщение автора поблагодарили: pitersky (2), axm2017 (4). |
06.05.2021, 14:07 | #4 |
Участник
|
PS На всякий случай домохозяйкам на заметку в SalesTaxDeclarationInfoItemizedExcel_HU та же фигня (отчет Sales tax declaration info Itemized Excel for HU).
|
|
06.05.2021, 15:28 | #5 |
Moderator
|
Цитата:
Ты там поинтересуйся при случае, не было ли у ваших зарубежных коллег случаев хронической икоты ? А то я вот совсем не понимаю, ЗАЧЕМ было делать такую мелкогранулированную систему, а потом ее же наглухо закрывать от расширений... |
|
06.05.2021, 15:47 | #6 |
Участник
|
Мне в таких случаях приходилось писать и такое (вместо трех строчек кода):
X++: SysDictClass sysDictClassCredManCreditControl_WHS = SysDictClass::newName(classStr(CredManCreditControl_WHS)); Object creditControl = sysDictClassCredManCreditControl_WHS.callStatic( staticMethodStr(CredManCreditControl_WHS, newFromDocumentStatusCheck), CredManDocumentStatusCheck::WHSShipment); sysDictClassCredManCreditControl_WHS.callObject( methodStr(CredManCreditControl, parmSalesTable), creditControl, origSalesTable); checkOK = sysDictClassCredManCreditControl_WHS.callObject( methodStr(CredManCreditControl, run), creditControl); |
|
|
За это сообщение автора поблагодарили: trud (1). |
07.05.2021, 09:05 | #7 |
Участник
|
Цитата:
Вот, например, сделали вы метод X++: public void test(str _arg)
Решения:
Последний раз редактировалось belugin; 07.05.2021 в 09:15. |
|
07.05.2021, 10:52 | #8 |
Участник
|
Цитата:
Но это не отменяет замечания что каждый метод создан отдельный класс. Вроде как цель ООП - это упросить сопровождение, а не сделать его более сложным. В последнее время очень много такого кода стало встречаться |
|
07.05.2021, 11:40 | #9 |
Участник
|
Цитата:
Доступ к полям таблицы происходит через конверсию в object - соответственно boxing/unboxing. Так же там есть всякая проверка доступа и т.д. Цитата:
довольно удобно получается.
Но это не отменяет замечания что каждый метод создан отдельный класс. Вроде как цель ООП - это упросить сопровождение, а не сделать его более сложным. В последнее время очень много такого кода стало встречаться |
|
07.05.2021, 11:53 | #10 |
Moderator
|
Посмотри на классы BankCurrencyReval* и все что с ними связано. Я когда-то эту задачу делал в один класс. Наверное по-хорошему можно было бы там логику класса на 3-4 реструктурировать (с учетом изменений в работе с финансовыми аналитиками в DAX2012). Но Микрософт создал 28 классов BankCurrencyReval*, три класса BankAccount*, добавил около 5-6 методов в разные таблицы и тщательно закрыл все это internal и hookable(false)
|
|
|
|