07.01.2008, 15:51 | #1 |
Участник
|
Khue Trinh: How to get Inventory On-hand number
Источник: http://khue.spaces.live.com/Blog/cns...A0C2!326.entry
============== This is a quick and dirty exmple:
Enjoy... Источник: http://khue.spaces.live.com/Blog/cns...A0C2!326.entry
__________________
Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору. |
|
07.01.2008, 16:10 | #2 |
Участник
|
вот и буржуйские программисты подтягиваются...
"quick and dirty"... и ни малейшего проблеска понимания того, что именно делается... ни малейшего желания разобраться со стандартными методами... грустно http://axapta.mazzy.ru/lib/inventsumdate/ |
|
07.01.2008, 16:19 | #3 |
Участник
|
Нет, не могу на это смотерть спокойно.
Во-первых, раз уж чел рассказывает про "On-hand number", то мог бы хотя бы метод использовать вмето тупого суммирования "непонятных" полей. Код бы получился более коротким и более наглядным. Заодно разобрался бы, что перепутал знаки и пропустил статус Зарегистрировано (хотя в списке полей запроса указал). X++: InventDim inventDim; InventSum inventSum; InventQty inventQty; ; while select sum(postedQty), sum(received), sum(deducted), sum(registered), sum(picked), sum(reservPhysical) from InventSum group by itemId join InventDim where inventSum.inventDimId == inventDim.inventDimId && inventSum.itemId == 'your item' && inventDim.inventLocationId == 'your WH' { inventQty += inventSum.availPhysical(); } info(strfmt('%1', inventQty)); Чел даже не предполагает, что цикл может вернуть несколько значений (тогда зачем использует while?). А все потому, что чел делает свертку по номенклатуре. Воистину "fast and dirty" поскольку при других условиях ему придется писать абсолютно новый код. Исправил в моем примере. |
|
07.01.2008, 16:31 | #4 |
Участник
|
и даже после такой модификации код все еще не будет оптимальным и универсальным.
ведь кто-то может заоптимизировать inventSum или добавить туда статусов и дополнительных полей. А этот австралийский индус жестко указывает список суммируемых полей в жестко написанном запросе. Разобраться с методом newQuery?... Нет это же "quick and dirty" программирование. На самом деле должно быть так: X++: Query = InventSum::newQuery(null, 'your item',DimCriteria, ParmCriteria, ParmGroupBy); QueryRun = new Qureyrun(Query); while( QueryRun.next() ) { inventSum = QueryRun.get(tablenum(InventSum)); inventQty += inventSum.availPhysical(); } info(strfmt('%1', inventQty)); Недели и месяцы, потраченные на оптимизацию производительности запросов не пропадают зря только потому, что какой-то индус написал прямой запрос к таблице. Но ведь для этого надо разобраться с параметрами. А это так сложно, чтобы делать "enjoy" от "fast and dirty" примера... |
|
|
За это сообщение автора поблагодарили: belugin (3). |
07.01.2008, 16:41 | #5 |
Участник
|
а теперь параметры
X++: Query Query; QueryRun QueryRun; InventDim DimCriteria; InventDimParm ParmCriteria; InventDimParm ParmGroupBy; ; ////////////// параметры ////////////// DimCriteria.clear(); DimCriteria.InventLocationId = 'your wh'; ParmCriteria.clear(); ParmCriteria.ItemIdFlag = NoYes::Yes; ParmCriteria.InventLocationIdFlag = NoYes::Yes; ParmGroupBy.clear(); ParmGroupBy.ItemIdFlag = NoYes::Yes; ////////////// цикл ////////////// Query = InventSum::newQuery(null, 'your item',DimCriteria, ParmCriteria, ParmGroupBy); QueryRun = new Qureyrun(Query); while( QueryRun.next() ) { inventSum = QueryRun.get(tablenum(InventSum)); inventQty += inventSum.availPhysical(); } info(strfmt('%1', inventQty)); Нет. Стал ли код более универсальным? Да. Стал ли код правильным? Еще не совсем. Не хватает проверки на допустимость склада - бывают номенклатуры, для которых склад неактивен. Но поскольку в "примере" рассматривается только одна номенклатура и только один склад - это несущественно. Вот если бы мы раскрывали цикл по нескольким номенклатурам и складам... Можно ли этот код использовать в качестве паттерна для дальнейшего использования? Да. А ведь достаточно было посмотреть на УЖЕ СУЩЕСТВУЮЩИЕ методы и чуть-чуть подумать... "fast and dirty", блин |
|
08.01.2008, 00:30 | #6 |
Участник
|
Ну, раз уж на то пошло, то думаю оптимальным вариантом здесь является использование класса InventDimOnHand - я про это ему в комментарии тоже написал
И самый лаконичный, и самый re-using existing code |
|
08.01.2008, 00:31 | #7 |
Участник
|
А вообще вроде блоггер сам неплохой - часто светится.
|
|
08.01.2008, 09:11 | #8 |
Участник
|
Цитата:
Вообще говоря, да. Было бы замечательно, если бы чел вместо "quick and dirty" примеров показал бы как правильно работать с классами. Чем классы отличаются друг от друга и в каких случаях лучше так, а в каких иначе... Было бы замечательно, если бы он рассказал что класс InventOnHand прекрасно заточен на получение итога по одной номенклатуре и одной складской аналитике. Но этот класс становится чертовски неэффективным в цикле при переборе. Было бы замечательно, если бы он рассказал о том как правильно перебирать итоги по разным номенклатурам и анлитикам в цикле. Было бы замечтаельно, если бы он проанализировал что это за уровни в InventDimOnHand и почему эта сволочь делает кучу запросов, собирает все в итератор, хранит результаты в памяти и занимается прочей ерундой вместо того, чтобы сделать один простой запрос и этим же запросом вернуть результаты (за это я этот класс и не люблю. Может быть, просто не понимаю? Может, расскажешь подробнее нафига надо было городить такую сложную и неочевидную обертку над простой, в общем то, сущностью?) Если человек хотел сказать, что: 1. InventSum хранит итоги по каждому конкретному InventDim (склад, цвет, размер, конфигурация, партия, серийный номер, паллета, ячейка) 2. Чтобы собрать итоги по одной аналитике (например, складу) придется просуммировать несколько InventSum. То так бы и сказал. Но чел написал "quick and dirty" пример. К тому же содержащий элементарные ошибки. Именно это и взбесило - убежденность автора, что данного примера будет достаточно для enjoy. |
|
08.01.2008, 09:21 | #9 |
Участник
|
Цитата:
Не. Этот класс используется сугубо в WMS. Этот класс позволяет хранить результаты и перебирать их повторно в алгоритме оптимального поиска ячеек. В остальных случаях этот класс явно избыточен, на мой взгляд. Кроме того, этот класс выбирает несколько результатов в цикле (!) при помощи InventOnHand. А inventOnHand заточен на получение итога по одной аналитике. В цикле этот класс чудовищно неэффективен. А следовательно, неэффективен и InventDimOnHand. По-моему, InventDimOnHand был и остается примером крайне неудачного использования инструмента InventOnHand. Разработчикам InventDimOnHand надо было использовать InventSum::newQuery, а не InventOnHand. Или я чего-то не понимаю? |
|
08.01.2008, 11:41 | #10 |
Участник
|
InventOnHand, конечно
Dim я туда случайно всунул, так как АХ не открыл, чтобы проверить, что это тот класс, который на уме. Сорри за запутывание Вот пример написал, что исправиться X++: static void InventOnHandExample(Args _args) { InventDim inventDim; InventDimParm inventDimParm; #define.InventLocationId("MW") #define.ItemId("ESB-005") ; inventDimParm.InventLocationIdFlag = NoYes::Yes; inventDim.InventLocationId = #InventLocationId; box::info(strFmt("%1", InventOnHand::newItemDim(#ItemId, inventDim, inventDimParm).availPhysical())); } А про InventSum::newQuery() - ты немного просто напутал, когда написал цикл. Ведь этот запрос, по сути, уже возвращает готовый запрос с агрегированием, поэтому цикла там никогда не будет - хотя код, естественно, будет работать. |
|
08.01.2008, 11:46 | #11 |
Участник
|
Цитата:
Цикла не будет только в этом примере. Я специально сделал группировку как у Тринха. При его группировке и условиях цикл действительно не нужен. В реальности параметры ParmCriteria, ParmGroupBy могут и не совпадать. А также ParmGroupBy может содержать больше галочек, чем ParmCriteria. Тогда цикл очень даже нужен. Кстати, InventOnHand как раз предполагает совпадение. За счет такого предположения они сократили число параметров и убрали ParmGroupBy. Я же старался написать действительно универсальный код, который можно использовать как паттерн в любых случаях. Какие бы галки не включили в ParmCriteria и ParmGroupBy - мой код будет работать корректно. |
|
08.01.2008, 11:49 | #12 |
Участник
|
Да. Единственное ограничение - не наод использовать конструкцию с InventOnHand внутри цикла. Только для одноразового запроса.
|
|
08.01.2008, 11:59 | #13 |
Участник
|
Кстати, если говорить об аккуратности и краткости при предположениях и в частных случаях...
Если нужно получить только по непустым складским аналитикам, то можно упростить и унифицировать инициализацию InventDimParm. Вот так. X++: static void InventOnHandExample(Args _args) { InventDim inventDim; InventDimParm inventDimParm; #define.InventLocationId("MW") #define.ItemId("ESB-005") ; inventDim.InventLocationId = #InventLocationId; inventDimParm.initFromInventDim(InventDim); // галочки берем из непустых полей InventDim info(strFmt("%1", InventOnHand::newItemDim(#ItemId,inventDim,inventDimParm).availPhysical() )); } |
|
08.01.2008, 12:06 | #14 |
SAP
|
Цитата:
This is a quick and dirty exmple:
Прежде чем писать надо поискать нет ли готового, а то вот вам. Абсолютно поддерживаю, что необходимо использовать уже имеющийся стандартный классы InventOnHand и т.д. Я бы постеснялся такое в свой блог писать, если бы он у меня был |
|
08.01.2008, 12:37 | #15 |
Участник
|
Ну, блог он на то и блог, что писать туда мона все-все, шо вздумается
|
|
11.01.2008, 19:45 | #16 |
Участник
|
Спасибо, что дали ссылку на эту тему.
Вопрос, чем этот код, Цитата:
Цитата:
Сообщение от mazzy
X++: InventDim inventDim; InventSum inventSum; InventQty inventQty; ; while select sum(postedQty), sum(received), sum(deducted), sum(registered), sum(picked), sum(reservPhysical) from InventSum group by itemId join InventDim where inventSum.inventDimId == inventDim.inventDimId && inventSum.itemId == 'your item' && inventDim.inventLocationId == 'your WH' { inventQty += inventSum.availPhysical(); } info(strfmt('%1', inventQty)); |
|
11.01.2008, 21:04 | #17 |
Участник
|
Ещё, по моему, у вас не хватает
X++: InventSum inventSum; ; ... while(QueryRun.next()) { inventSum = QueryRun.get(tablenum(InventSum)); ..... } |
|
|
За это сообщение автора поблагодарили: mazzy (5). |
11.01.2008, 22:23 | #18 |
Участник
|
Цитата:
Поэтому вызов стандартного метода будет работать всегда (если только работу не проводят в стиле quick and dirty). А жесткий селект не всегда правильно и не всегда оптимально. Да, вы совершенно правы. Спасибо. |
|
|
За это сообщение автора поблагодарили: glibs (2). |