|
24.03.2020, 14:30 | #1 |
Участник
|
Наткнулся в недрах класса JournalRunBaseBatch
X++: public container pack() { throw error(Error::missingOverload(funcName())); } Здесь как бы разница есть, перегружен метод, или переопределен. Причем в Х++ сроду не было перегруженных методов. Видимо, не сильно-то и важно. Заходим внутрь и видим: X++: //Do not use! //Declare method as abstract instead or call Error::missingOverride(); #obsolete static LabelType missingOverload(str name) { return Error::missingOverride(name); } Но что мешало сразу использовать missingOverride()? Напомню, кто может не въехал. Override - переопределение метода в рамках наследования. Overload - перегрузка метода, т.е. в теле одного класса мы можем разместить дофига методов с одним и тем же именем, но разными параметрами. Что очень распространено в C#, Java и Delphi. Такое чувство, что разработчики MS просто сами не сильно понимают в чем разница.
__________________
// no comments |
|
15.06.2020, 17:15 | #2 |
Модератор
|
Гендерно- и расово-нейтральный новояз прекрасен
__________________
-ТСЯ или -ТЬСЯ ? |
|
23.12.2020, 18:44 | #3 |
Участник
|
В этом месте у пользователя происходит раздвоение личности. Ошибки нет, но журнал не разносится.
Все-таки какая Аксапта прикольная, смеялся несколько минут над этим.
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/ |
|
06.07.2021, 18:40 | #4 |
Участник
|
Вот не знаю, это ошибка или сознательно сделали
dax2012R3 Табличный метод PurchTable.initFromPurchAgreementHeader() X++: select firstonly DeliveryPostalAddress, DeliveryName, Project, ContactPerson, CashDiscountCode, MiscChargeGroup, DeliveryTerm, DeliveryMode, PaymentSchedule, PaymentTerms from agreementHeaderDefault where agreementHeaderDefault.AgreementHeader == _purchAgreementHeader.RecId join firstonly MethodOfPayment , PaymentSpecification , BuyerGroup , VendorInvoiceAccount , PurchasePool from purchAgreementHeaderDefault where purchAgreementHeaderDefault.PurchaseAgreementHeader == _purchAgreementHeader.RecId // <GEERU> outer join firstonly RecId, InventProfileType, InventProfileId, VendPostingProfile, vatOperationCode, vatChargeSource from purchAgreementHeaderExt where purchAgreementHeaderExt.AgreementHeader == _purchAgreementHeader.RecId // </GEERU> ; В этом был какой-то глубокий смысл или "так получилось" ?
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
27.07.2021, 11:24 | #5 |
Участник
|
Наткнулся на прелести обновления индексированных полей InMemory таблиц
Пример 3 разных попыток обновления X++: TmpFontName tmp; ; //(update_recordset) delete_from tmp; tmp.insert(); update_recordset tmp setting FontName = tmp.FontName + 'a'; while select tmp {info (tmp.FontName);} //(select forupdate) delete_from tmp; tmp.insert(); while select forupdate tmp{ tmp.FontName += 'a'; tmp.update(); } while select tmp {info (tmp.FontName);} //(select forupdate order) delete_from tmp; tmp.insert(); while select forupdate tmp order recid{ tmp.FontName += 'a'; tmp.update(); } while select tmp {info (tmp.FontName);} Цитата:
Сообщение (16:16:38)
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa a |
|
|
За это сообщение автора поблагодарили: dech (5), axm2017 (4). |
26.11.2021, 16:48 | #6 |
Участник
|
Axapta 2012 R3
Расчеты с клиентами - Журналы - Платежи - Журнал платежей Создаем первую строку в журнале. Вводим какого-то клиента Создаем вторую строку в журнале. Вводит другого клиента Стоя на второй строке журнала нажимаем "Фукнции - Сопоставление". Помечаем проводки для сопоставления. Потом не закрывая форму сопоставлений возвращаемся на форму строк журнала и встаем на первую строку Потом возвращаемся на форму сопоставлений и закрываем её И вуаля - в первую строку журнала записывается аналитика из клиента, который указан для второй строки. А потом удивляемся при сведении балансов.
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/ |
|
|
За это сообщение автора поблагодарили: S.Kuskov (5). |
15.12.2021, 11:04 | #7 |
Участник
|
Как бы и ошибок нет, Но индусы снова поражают своей логикой!
В классе PurchTableType: X++: /// <summary> /// Checks if the invoice can be updated. /// </summary> /// <returns> /// Returns true if the invoice can be updated. /// </returns> // <GIN> public boolean canInvoiceBeUpdated_IN() { boolean ok = true; ok = this.mayInvoiceBeUpdated(); if (ok && !VendTable::canVendorBeUpdated(purchTable.OrderAccount, purchTable.InvoiceAccount, DocumentStatus::Invoice)) { ok = false; } if (ok) { if (purchTable.InterCompanyOrder && purchTable.InterCompanyOriginalSalesId && purchTable.InterCompanyDirectDelivery) { ok = (!purchTable.interCompanyEndpointActionPolicy().PostPurchInvoice && purchTable.interCompanySalesTable().SalesStatus == SalesStatus::Invoiced); } ok = ok && true; // Что это за дикость? } if (ok) { ok = this.checkPurchQty(DocumentStatus::Invoice); } return ok; } // </GIN>
__________________
// no comments |
|
15.12.2021, 12:27 | #8 |
Участник
|
X++: ok = ok && true; До DAX2012, в которой точки останова срабатывают на скобке, завершающей блок кода или метода, иногда сам так делал. Правда в рабочем приложении такое видеть, конечно, дикость. |
|
15.12.2021, 13:58 | #9 |
Участник
|
Я обычно завожу в глобале метод пустышку с именем dummy или empty и ставлю в код его вызов.
|
|
19.12.2021, 17:18 | #10 |
Участник
|
Цитата:
Следующий if (ok) вполне пригоден для просмотра значений переменных. Скорее выглядит как копипаста, когда лишний код убрали, оставив такую конструкцию.
__________________
// no comments |
|
15.12.2021, 18:34 | #11 |
Moderator
|
Не вполне баг кодинга, но все равно - неприятно поразившая меня фича D365FO.
С древних времен версии 2.1 и по крайней мере до последнего релиза DAX2012, удаление складских проводок при уменьшении количества в заказе шло в порядке OnOrder->ReserveOrdered->ReservePhysical. Все это происходило независимо от наличия/остуствия складской маркировки. В D365FO, добавили два прохода: Сначала оно обрабатывает в таком порядке складские проводки без маркировки, а потом с маркировкой. У меня у клиента часто возникает такая ситуация: Клиент заказал допустим 40 подарков к рождеству; На складе удалось зарезервировать 30, и еще 10 примаркировали к закупке с ожидаемым сроком доставки 22.12. Потом клиент звонит и говорит что не хочет ждать, хочет 30 штук сразу, а вместо 10 недостающих подарков купит что-то другое в другой фирме. В традиционных версиях DAX, если уменьшить количество в строке заказа до 30, то система оставит 30 штук физически зарезервированых и удалит складскую проводку на 10 штук в статусе "Зарезервировано в заказаных". В D365FO, она выкинет 10 штук из физически зарезервированой проводки (поскольку она не примаркирована), и оставит в итоге 20 штук зарезервированых на складе и 10 штук в заказаных. Так что если мы попытаемся отгрузить клиенту обещенные прямо сейчас 30 штук, система скажет что в этот раз мы можем отгрузить только 20 штук и тп. Единственный выход - отмаркировать злополучную складскую проводку от закупки до удаления количества... |
|
|
За это сообщение автора поблагодарили: sukhanchik (6), twilight (3). |
17.01.2022, 10:20 | #12 |
Участник
|
Может чего то не догоняю но в форме PurchTotals (ax 2012) переменная
PurchTotals purchTotals; не используется а существует для фана. |
|
17.01.2022, 13:50 | #13 |
Участник
|
Скорее всего, когда переделывали форму на разные таблицы-источники просто забыли удалить уже не нужную переменную из ClassDeclaration. Или была идея, что класс PurchTotals также будет общий. Возможно, как класс-родитель
Кстати, если есть сомнения, то просто закомментируйте объявление переменной. Формы-то наследоваться не могут. Не будет ошибок компиляции, значит реально не нужна
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
17.01.2022, 14:01 | #14 |
Участник
|
|
|
26.01.2022, 16:52 | #15 |
Участник
|
В D365FO семейство классов RAssetProposal очень "занятно" распаковывает параметры в unpack(), из-за чего не так просто добавлять в это семейство новые параметры для сохранения в pack()/unpack().
Коллега недавно наткнулся на проблему, пытаясь применить к этому семейству рекомендации по расширению наследников RunBase. В рекомендациях говорится, что в pack() вашего класса-расширения нужно написать примерено так: X++: public container pack() { container packedClass = next pack(); return SysPackExtensions::appendExtension(packedClass, classStr(MySysUserLogCleanup_Extension), this.myPack()); } X++: public boolean unpack(container _packedClass) { boolean result = next unpack(_packedClass); if (result) { container myState = SysPackExtensions::findExtension(_packedClass, classStr(MySysUserLogCleanup_Extension)); result = this.myUnpack(myState); //Also unpack the extension } return result; } Вот как бы вы работали с queryRun в pack/unpack? Обычно это выглядит так: X++: public container pack() { return [#CurrentVersion, #CurrentList, queryRun.pack()]; } X++: public boolean unpack(container _packedClass) { Version version = RunBase::getVersion(_packedClass); boolean ret = true; switch (version) { case #CurrentVersion : container packedQuery; [version, #CurrentList, packedQuery] = _packedClass; if (SysQuery::isPackedOk(packedQuery)) // ... X++: [version, #CurrentList, packedQuery] = _packedClass; X++: return [#CurrentVersion, #CurrentList, queryRun.pack()]; Но локализаторы же хитрее всех, поэтому они считают, что их запакованный queryRun всегда идет последним, и пишут вот что: X++: public boolean unpack(container packedClass) { Integer version = conPeek(packedClass,1); container packedQuery = conPeek(packedClass, conLen(packedClass)); |
|
|
За это сообщение автора поблагодарили: ax_mct (5), S.Kuskov (5), dech (10), Pandasama (2). |
27.01.2022, 03:00 | #16 |
Banned
|
Цитата:
Спасибо за опыт! Делаю вывод что в топку их инструкцию так любое их обновление unpack может вызвать подобный сценарий ошибки. Часв два времени сделать свою таблицу и отладить код для хранения своего контейнера. То есть: CoC на pack/unpack но без изменений того что кладется и вынимается. Собственная таблица для хранения своего дополнительного контейнера. Напрягает что в любом будущем автоматическом накате изменений может быть такая ошибка. Сейчас OK, а скажем через год добавят диалоговый параметр и плохо напишут код в unpack. Думаю что это самый классический случай когда будущее изменение вендора может сломать приложение без ошибок компиляции. Кто будет виноват. Мы. Из-за нашего расширения ошибка - да. Подстава. |
|
27.01.2022, 16:40 | #17 |
Участник
|
Ну может автор хотел чтобы вы в каждом экстеншене паковали его query. Имеет же право
|
|
27.01.2022, 19:39 | #18 |
Banned
|
Тут ведь не только базовые классы но и абсолютно все их экстеншен должны корректно обращаться с общим для всех контейнером. Достаточно любого соседнего экстеншен с подобной адресацией. Причем этот экстеншен типа работает, а ваше его ломает.
|
|
19.08.2022, 14:08 | #19 |
Участник
|
Долго не мог понять какого моя ER конфигурация (технически стандартный функционал ER\SSRS накладных) отказывается работать
Пришлось заглянуть в код. Много думал на тему рукожопства с ограничением по RU. |
|
02.09.2022, 15:11 | #20 |
Участник
|
Делал доклад по ER
Традиционно (когда еще замечать косяки как не в ходе показа?) в его процессе заметил возможность добавить void в модель Попробовал ради интереса. Много думал о команде ER и нехватке тестеров. |
|