Модуль розницы в 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);
}
}
- изначально, допустим, doNext == true, doSelect == true; количества InventTrans.Qty, addQty, addReserv, reserveMax и т.п. в целом ожидаются неположительные;
- входим внутрь условия if (countryRegion_RU ...
- выбирается запись InventTrans лота, под который нужно зарезервировать товар, при этом в записи Qty == 0
- считается addQty, получается 0, считается reserveMax, получается некое отрицательное число при наличии остатка
- addQty сравнивается с reserveMax, в итоге doNext становится false
- условие if (addQty < 0) не выполняется, в итоге doSelect становится false
- затем проверяется еще несколько условий, в итоге doNext становится опять true!
- возвращаемся на while (doNext) - и всё, зациклились
Первое пришедшее в голову решение - выбирать InventTrans с условием Qty != 0, коллега, воспризведший зависание на AX 2009, также предложил добавить код в InventTrans.updateSumUp(), чтобы он при this.Qty == 0 не обновлял, а удалял текущую запись.
В целом, я, конечно, понимаю, что проводки "Заказано" с нулевым количеством - это подстава, но, по-моему, зависание намертво при резервировании таких проводок - еще большая подстава