Показать сообщение отдельно
Старый 28.10.2015, 18:52   #1  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5788 (200) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Резервирование зависает на нулевом количестве "Заказано"
Модуль розницы в AX 2012 подкинул очередной сюрприз: строки чеков, группируемые в один лот по ряду признаков, дали с учетом возвратов тем же днем нулевое количество, причем, что самое главное, проводка InventTrans по лоту при этом каким-то образом не удалилась. Т.е. на выходе получился InventTrans в статусе расхода "Заказано" и с количеством 0.
Самое интересное началось на попытке зарезервировать соотв. лот при ненулевых остатках на складе: резервирование зависло в бесконечном цикле. Происходит это в \Classes\InventUpd_Reservation\updateReserveMore:

X++:
while (doNext)
{
    /* ... */
    // <GEERU>
    if (   (countryRegion_RU  && (inventSum.AvailOrdered + inventSum.OnOrder) != 0 && movement.checkDimInventOwnerId_RU(inventDim, false))
        || (!countryRegion_RU && (loopReserveType == 0 || (inventSum.AvailOrdered + inventSum.OnOrder))))
    // </GEERU>
    {
        if (doSelect)
        {
            if (inventDimParmIsAllYes && inventDimCriteria.InventDimId)
            {
                select firstonly forupdate inventTrans
                    where inventTrans.InventTransOrigin     == movement.inventTransOriginId()
                       && inventTrans.TransChildType        == movement.transChildType()
                       && inventTrans.TransChildRefId       == movement.transChildRefId()
                       && inventTrans.StatusReceipt         == StatusReceipt::None
                       && inventTrans.StatusIssue           == StatusIssue::OnOrder
                       && inventTrans.InventDimId           == inventDimCriteria.InventDimId;
            }
            else
            {
                select firstonly forupdate inventTrans
                    where inventTrans.InventTransOrigin     == movement.inventTransOriginId()
                       && inventTrans.TransChildType        == movement.transChildType()
                       && inventTrans.TransChildRefId       == movement.transChildRefId()
                       && inventTrans.StatusReceipt         == StatusReceipt::None
                       && inventTrans.StatusIssue           == StatusIssue::OnOrder;
            }
        }
        if (! inventTrans)
        {
            break;
        }
        addQty = inventTrans.Qty > addReserv ? inventTrans.Qty : addReserv;
        /* ... */
        if (cwItem)
        {
            /* ... */
        }
        else if (addQty <= reserveMax)
        {
            addQty      = reserveMax;
            doNext      = true;
            tmpReserved = 0;
        }
        else
        {
            doNext = false;
        }
        if (addQty < 0)
        {
            /* ... */
        }
        else
        {
            doSelect = false;
        }
        if ((!cwItem
                && addReserv >= 0)
            || (cwItem
                && addReserv >= 0
                && cwAddReserv >= 0))
        {
            doNext = false;
        }
        else if (doNext && !pdsOverageQty)
        {
            doNext = setInventSum(false);
            tmpReserved = 0;
        }
        else
        {
            pdsOverageQty = 0;
            doNext = true;
        }
    }
    else
    {
        doNext = setInventSum(false);
    }
}
  1. изначально, допустим, doNext == true, doSelect == true; количества InventTrans.Qty, addQty, addReserv, reserveMax и т.п. в целом ожидаются неположительные;
  2. входим внутрь условия if (countryRegion_RU ...
  3. выбирается запись InventTrans лота, под который нужно зарезервировать товар, при этом в записи Qty == 0
  4. считается addQty, получается 0, считается reserveMax, получается некое отрицательное число при наличии остатка
  5. addQty сравнивается с reserveMax, в итоге doNext становится false
  6. условие if (addQty < 0) не выполняется, в итоге doSelect становится false
  7. затем проверяется еще несколько условий, в итоге doNext становится опять true!
  8. возвращаемся на while (doNext) - и всё, зациклились
Первое пришедшее в голову решение - выбирать InventTrans с условием Qty != 0, коллега, воспризведший зависание на AX 2009, также предложил добавить код в InventTrans.updateSumUp(), чтобы он при this.Qty == 0 не обновлял, а удалял текущую запись.
В целом, я, конечно, понимаю, что проводки "Заказано" с нулевым количеством - это подстава, но, по-моему, зависание намертво при резервировании таких проводок - еще большая подстава
За это сообщение автора поблагодарили: Logger (3), Товарищ ♂uatr (1).