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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 07.01.2008, 15:51   #1  
Blog bot is offline
Blog bot
Участник
 
25,617 / 848 (80) +++++++
Регистрация: 28.10.2006
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:

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.PostedQty

                + inventSum.Received
                + inventSum.Deducted
                - inventSum.Picked
                - inventSum.ReservPhysical;
}
info(strfmt('%1', inventQty));
 
Enjoy...

Источник: http://khue.spaces.live.com/Blog/cns...A0C2!326.entry
__________________
Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору.
Старый 07.01.2008, 16:10   #2  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
вот и буржуйские программисты подтягиваются...
"quick and dirty"...
и ни малейшего проблеска понимания того, что именно делается...
ни малейшего желания разобраться со стандартными методами...
грустно

http://axapta.mazzy.ru/lib/inventsumdate/
__________________
полезное на axForum, github, vk, coub.
Старый 07.01.2008, 16:19   #3  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Нет, не могу на это смотерть спокойно.

Во-первых, раз уж чел рассказывает про "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" поскольку при других условиях ему придется писать абсолютно новый код.
Исправил в моем примере.
__________________
полезное на axForum, github, vk, coub.
Старый 07.01.2008, 16:31   #4  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
и даже после такой модификации код все еще не будет оптимальным и универсальным.
ведь кто-то может заоптимизировать 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" примера...
__________________
полезное на axForum, github, vk, coub.
За это сообщение автора поблагодарили: belugin (3).
Старый 07.01.2008, 16:41   #5  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
а теперь параметры

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", блин
__________________
полезное на axForum, github, vk, coub.
Старый 08.01.2008, 00:30   #6  
kashperuk is offline
kashperuk
Участник
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,361 / 2084 (78) +++++++++
Регистрация: 30.05.2004
Адрес: Atlanta, GA, USA
Ну, раз уж на то пошло, то думаю оптимальным вариантом здесь является использование класса InventDimOnHand - я про это ему в комментарии тоже написал

И самый лаконичный, и самый re-using existing code
Старый 08.01.2008, 00:31   #7  
kashperuk is offline
kashperuk
Участник
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,361 / 2084 (78) +++++++++
Регистрация: 30.05.2004
Адрес: Atlanta, GA, USA
А вообще вроде блоггер сам неплохой - часто светится.
Старый 08.01.2008, 09:11   #8  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от kashperuk Посмотреть сообщение
Ну, раз уж на то пошло, то думаю оптимальным вариантом здесь является использование класса InventDimOnHand - я про это ему в комментарии тоже написал

И самый лаконичный, и самый re-using existing code
Хм... Спасибо. А почему не InventOnHand?

Вообще говоря, да. Было бы замечательно, если бы чел вместо "quick and dirty" примеров показал бы как правильно работать с классами. Чем классы отличаются друг от друга и в каких случаях лучше так, а в каких иначе...

Было бы замечательно, если бы он рассказал что класс InventOnHand прекрасно заточен на получение итога по одной номенклатуре и одной складской аналитике. Но этот класс становится чертовски неэффективным в цикле при переборе.

Было бы замечательно, если бы он рассказал о том как правильно перебирать итоги по разным номенклатурам и анлитикам в цикле.

Было бы замечтаельно, если бы он проанализировал что это за уровни в InventDimOnHand и почему эта сволочь делает кучу запросов, собирает все в итератор, хранит результаты в памяти и занимается прочей ерундой вместо того, чтобы сделать один простой запрос и этим же запросом вернуть результаты (за это я этот класс и не люблю. Может быть, просто не понимаю? Может, расскажешь подробнее нафига надо было городить такую сложную и неочевидную обертку над простой, в общем то, сущностью?)

Если человек хотел сказать, что:
1. InventSum хранит итоги по каждому конкретному InventDim (склад, цвет, размер, конфигурация, партия, серийный номер, паллета, ячейка)
2. Чтобы собрать итоги по одной аналитике (например, складу) придется просуммировать несколько InventSum.

То так бы и сказал.

Но чел написал "quick and dirty" пример. К тому же содержащий элементарные ошибки.
Именно это и взбесило - убежденность автора, что данного примера будет достаточно для enjoy.
__________________
полезное на axForum, github, vk, coub.
Старый 08.01.2008, 09:21   #9  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от kashperuk Посмотреть сообщение
Ну, раз уж на то пошло, то думаю оптимальным вариантом здесь является использование класса InventDimOnHand
Посмотрел еще раз.
Не. Этот класс используется сугубо в WMS. Этот класс позволяет хранить результаты и перебирать их повторно в алгоритме оптимального поиска ячеек.

В остальных случаях этот класс явно избыточен, на мой взгляд.
Кроме того, этот класс выбирает несколько результатов в цикле (!) при помощи InventOnHand. А inventOnHand заточен на получение итога по одной аналитике. В цикле этот класс чудовищно неэффективен. А следовательно, неэффективен и InventDimOnHand.

По-моему, InventDimOnHand был и остается примером крайне неудачного использования инструмента InventOnHand. Разработчикам InventDimOnHand надо было использовать InventSum::newQuery, а не InventOnHand.

Или я чего-то не понимаю?
__________________
полезное на axForum, github, vk, coub.
Старый 08.01.2008, 11:41   #10  
kashperuk is offline
kashperuk
Участник
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,361 / 2084 (78) +++++++++
Регистрация: 30.05.2004
Адрес: Atlanta, GA, USA
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()));
}
Очень аккуратно, imho.

А про InventSum::newQuery() - ты немного просто напутал, когда написал цикл. Ведь этот запрос, по сути, уже возвращает готовый запрос с агрегированием, поэтому цикла там никогда не будет - хотя код, естественно, будет работать.
Старый 08.01.2008, 11:46   #11  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от kashperuk Посмотреть сообщение
А про InventSum::newQuery() - ты немного просто напутал, когда написал цикл. Ведь этот запрос, по сути, уже возвращает готовый запрос с агрегированием, поэтому цикла там никогда не будет - хотя код, естественно, будет работать.
Я думал об этом когда писал пример

Цикла не будет только в этом примере. Я специально сделал группировку как у Тринха. При его группировке и условиях цикл действительно не нужен. В реальности параметры ParmCriteria, ParmGroupBy могут и не совпадать. А также ParmGroupBy может содержать больше галочек, чем ParmCriteria. Тогда цикл очень даже нужен.

Кстати, InventOnHand как раз предполагает совпадение. За счет такого предположения они сократили число параметров и убрали ParmGroupBy.

Я же старался написать действительно универсальный код, который можно использовать как паттерн в любых случаях. Какие бы галки не включили в ParmCriteria и ParmGroupBy - мой код будет работать корректно.
__________________
полезное на axForum, github, vk, coub.
Старый 08.01.2008, 11:49   #12  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от kashperuk Посмотреть сообщение
Очень аккуратно, imho.
Да. Единственное ограничение - не наод использовать конструкцию с InventOnHand внутри цикла. Только для одноразового запроса.
__________________
полезное на axForum, github, vk, coub.
Старый 08.01.2008, 11:59   #13  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от kashperuk Посмотреть сообщение
Очень аккуратно, imho.
Кстати, если говорить об аккуратности и краткости при предположениях и в частных случаях...
Если нужно получить только по непустым складским аналитикам, то можно упростить и унифицировать инициализацию 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()
    ));
}
__________________
полезное на axForum, github, vk, coub.
Старый 08.01.2008, 12:06   #14  
konopello is offline
konopello
SAP
SAP
 
628 / 76 (4) ++++
Регистрация: 08.11.2005
Адрес: Минск
Цитата:
This is a quick and dirty exmple:
за такое руки отрывать надо.

Прежде чем писать надо поискать нет ли готового, а то вот вам.

Абсолютно поддерживаю, что необходимо использовать уже имеющийся стандартный классы InventOnHand и т.д.

Я бы постеснялся такое в свой блог писать, если бы он у меня был
Старый 08.01.2008, 12:37   #15  
kashperuk is offline
kashperuk
Участник
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,361 / 2084 (78) +++++++++
Регистрация: 30.05.2004
Адрес: Atlanta, GA, USA
Цитата:
Сообщение от konopello Посмотреть сообщение
Я бы постеснялся такое в свой блог писать, если бы он у меня был
Ну, блог он на то и блог, что писать туда мона все-все, шо вздумается
Старый 11.01.2008, 19:45   #16  
longson is offline
longson
Участник
 
231 / 49 (2) +++
Регистрация: 12.12.2006
Адрес: Москва
Спасибо, что дали ссылку на эту тему.

Вопрос, чем этот код,

Цитата:
Сообщение от mazzy Посмотреть сообщение

На самом деле должно быть так:
X++:
Query = InventSum::newQuery(null, 'your item',DimCriteria, ParmCriteria, ParmGroupBy);
QueryRun = new Qureyrun(Query);
while( QueryRun.next() )
{
    inventQty += inventSum.availPhysical();
}
info(strfmt('%1', inventQty));
...
универсальнее этот код, быстродействием или ещё чем-то ?

Цитата:
Сообщение от 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  
longson is offline
longson
Участник
 
231 / 49 (2) +++
Регистрация: 12.12.2006
Адрес: Москва
Ещё, по моему, у вас не хватает

X++:
InventSum inventSum;
;

...

while(QueryRun.next())
 {
   inventSum = QueryRun.get(tablenum(InventSum));
   .....
 }
}
За это сообщение автора поблагодарили: mazzy (5).
Старый 11.01.2008, 22:23   #18  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от longson Посмотреть сообщение
Вопрос, чем этот код,
универсальнее этот код, быстродействием или ещё чем-то ?
я уже писал. если кто-то добавит статусов и/или полей в inventSum, то этот кто-то должен обеспечить, чтобы стандартные методы работали правильно и быстро. Если кто-то займется оптимизацией, то должен будет выполнить оптимизацию метода newQuery.

Поэтому вызов стандартного метода будет работать всегда (если только работу не проводят в стиле quick and dirty).
А жесткий селект не всегда правильно и не всегда оптимально.

Цитата:
Сообщение от longson Посмотреть сообщение
Ещё, по моему, у вас не хватает

X++:
   inventSum = QueryRun.get(tablenum(InventSum));
Да, вы совершенно правы. Спасибо.
__________________
полезное на axForum, github, vk, coub.
За это сообщение автора поблагодарили: glibs (2).
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Khue Trinh: Adjust Standard Cost of Item Blog bot DAX Blogs 1 30.04.2008 15:08
Khue Trinh: Inventory Min/Max Key Blog bot DAX Blogs 0 13.01.2008 19:32
November princess: How does Dynamics Ax perform the inventory settlement for closing process Blog bot DAX Blogs 0 11.01.2008 22:10
Khue Trinh: RESERVATION AT A GLANCE Blog bot DAX Blogs 0 07.01.2008 15:51
Khue Trinh: Be careful with Inventory journal Blog bot DAX Blogs 0 07.01.2008 15:51

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

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

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