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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 10.11.2020, 14:17   #1  
Sergey Petrov is offline
Sergey Petrov
Участник
 
80 / 19 (1) ++
Регистрация: 03.04.2007
Адрес: Saint-Petersburg, Russia
Закрытие склада во вторичной валюте
Коллеги, обнаружил что в методе класса \Classes\InventCostItemDim\updateMarking используется отбор проводок определённого типа:
X++:
    // load
    while select forupdate inventTrans
        index hint OpenItemIdx
        where inventTrans.ValueOpen         == InventTransOpen::Yes     &&
              inventTrans.ItemId            == _itemId                  &&
              inventTrans.InventRefTransId  != ''
        join inventDim
        where inventDim.InventDimId == inventTrans.InventDimId
    {
...
В классе InventCostItemDimSecCur_RU этот метод не перекрыт.
Таким образом, при закрытии склада во вторичной валюте после закрытия в основной, мы не можем отобрать нужные проводки (потому что фильтрация по inventTrans.ValueOpen == InventTransOpen::Yes) и вообще не получаем сопоставлений, аналогичных тем, что были в основной валюте.

То же самое видим в методе класса \Classes\InventCostItemDim\updateServiceItemTrans:
X++:
    while select forupdate inventTrans
        index hint OpenItemIdx
        where inventTrans.ValueOpen         == InventTransOpen::Yes         &&
              inventTrans.ItemId            == _itemId                      &&
             (inventTrans.StatusIssue       == StatusIssue::Sold            ||
              inventTrans.StatusReceipt     == StatusReceipt::Purchased)    &&
              inventTrans.DateStatus        <= inventClosing.TransDate      &&
              inventTrans.InventRefTransId  == '' //marked service item transactions will be settled according to marking principle

    {
...
Но перекрытого метода в потомке-классе InventCostItemDimSecCur_RU нет. Соответственно, результат тот же - мы не получаем сопоставлений во вторичной валюте, аналогичных сопоставлениям в основной валюте.

Заметили только что, потому что наша бизнес-логика активно использует эти сопоставления (коррекции себестоимости) в основной и во вторичной валюте.

Думаю исправить сие вручную. Но, может, кому известны какие-нибудь подводные камни?
__________________
MS Dynamics AX 2009

Kernel 5.0.1600.4110
Application 5.0.1500.6491
Старый 10.11.2020, 15:32   #2  
SRF is offline
SRF
Участник
MCBMSS
Axapta Retail User
 
362 / 542 (19) +++++++
Регистрация: 08.08.2007
Записей в блоге: 1
Если есть возможность загляните в AX 2012 R3, может быть там не только эти баги исправлены, вот как выглядят данные выборки в InventCostItemDim

X++:
countryRegion_RU = SysCountryRegionCode::isLegalEntityInCountryRegion([#isoRU]);
X++:
    // load
    while select forupdate inventTrans
        index hint OpenItemIdx
        // <GEERU>
        where (countryRegion_RU
           && ((inventTransCurrency                     == InventTransCurrency_RU::PrimaryCur
           &&   inventTrans.ValueOpen                   == InventTransOpen::Yes)
           ||  (inventTransCurrency                     == InventTransCurrency_RU::SecondaryCur
           &&   inventTrans.ValueOpenSecCur_RU          == InventTransOpen::Yes))
           || (!countryRegion_RU
           && (inventTrans.ValueOpen                    == InventTransOpen::Yes)))
        // </GEERU>
           && inventTrans.ItemId                        == _itemId
           && inventTrans.MarkingRefInventTransOrigin
        join inventDim
        where inventDim.InventDimId == inventTrans.InventDimId
X++:
protected void updateServiceItemTrans(ItemId _itemId)
{
    InventTrans         inventTrans;
    InventSettlement    inventSettlement;

    RecordInsertList    recordInsertList = new RecordInsertList(tableNum(InventSettlement),true,true);

    // Optimization note: All columns are expected to be included in the index
    while select forupdate inventTrans
        index hint OpenItemIdx
        // <GEERU>
        where ((countryRegion_RU
           && ((inventTransCurrency             == InventTransCurrency_RU::PrimaryCur
           &&   inventTrans.ValueOpen           == InventTransOpen::Yes)
           ||  (inventTransCurrency             == InventTransCurrency_RU::SecondaryCur
           &&   inventTrans.ValueOpenSecCur_RU  == InventTransOpen::Yes)))
           || (!countryRegion_RU
           && inventTrans.ValueOpen         == InventTransOpen::Yes))
        // </GEERU>
          &&  inventTrans.ItemId            == _itemId
          && (inventTrans.StatusIssue       == StatusIssue::Sold
          ||  inventTrans.StatusReceipt     == StatusReceipt::Purchased)
          &&  inventTrans.DateStatus        <= inventClosing.TransDate
          &&  inventTrans.MarkingRefInventTransOrigin   == 0 // marked service item transactions will be settled according to marking principle

    {
        // <GEERU>
        if (countryRegion_RU)
        {
            inventSettlement = this.initInventSettlement(inventTrans,
                                                         inventTransCurrency == InventTransCurrency_RU::PrimaryCur ? inventTrans.financialOpenQty()   : inventTrans.financialOpenQtySecCur_RU(),
                                                         inventTransCurrency == InventTransCurrency_RU::PrimaryCur ? inventTrans.financialOpenValue() : inventTrans.financialOpenValueSecCur_RU(),
                                                         0,
                                                         InventSettleModel::ServiceItem,
                                                         inventTrans.Qty >= 0 ? InventSettleType::Receipt : InventSettleType::Issue,
                                                         #initLedgerDrop
                                                         );
        }
        else
        {
        // </GEERU>
            inventSettlement = this.initInventSettlement(inventTrans,
                                                         inventTrans.financialOpenQty(),
                                                         inventTrans.financialOpenValue(),
                                                         0,
                                                         InventSettleModel::ServiceItem,
                                                         inventTrans.Qty >= 0 ? InventSettleType::Receipt : InventSettleType::Issue,
                                                         #initLedgerDrop
                                                         );
        // <GEERU>
        }
        // </GEERU>

        inventSettlement.SettleTransId      = InventSettlement::nextSettleTransId();
        inventSettlement.insertUsingInsertList(recordInsertList);

        // <GEERU>
        if (!countryRegion_RU
            || inventTransCurrency == InventTransCurrency_RU::PrimaryCur)
        {
        // </GEERU>
            inventTrans.QtySettled             += inventTrans.financialOpenQty();
            inventTrans.CostAmountSettled      += inventTrans.financialOpenValue();
        // <GEERU>
        }
        else
        {
            inventTrans.QtySettledSecCur_RU        += inventTrans.financialOpenQtySecCur_RU();
            inventTrans.CostAmountSettledSecCur_RU += inventTrans.financialOpenValueSecCur_RU();
        }
        // </GEERU>
        this.updateCostAmountStd(inventTrans);
        inventTrans.update();
    }

    recordInsertList.insertDatabase();
}
В DAX2009 насколько я помню регион как то по другому определяется, но смысл думаю ясен.
__________________
Sergey Nefedov
За это сообщение автора поблагодарили: Sergey Petrov (1).
Старый 10.11.2020, 16:03   #3  
SRF is offline
SRF
Участник
MCBMSS
Axapta Retail User
 
362 / 542 (19) +++++++
Регистрация: 08.08.2007
Записей в блоге: 1
Но это далеко не все артефакты вторичного закрытия в валюте, на одном приложении делал вот такие исправления в DAX2012 R3, думаю в AX2009 такая же беда

InventCostItemDim\updateReceiptAdjustmentTrans

X++:
            while select forceplaceholders pessimisticlock
                #settlementFieldList from settlementReceipt
                index hint RecIdTypeIdx
                where settlementReceipt.TransRecId      == _receipt.RecId
                   && settlementReceipt.SettleType      == InventSettleType::Receipt
                   && settlementReceipt.InventTransId   == _receipt.inventTransOrigin().InventTransId
                   // <GEERU>
                   && (!countryRegion_RU || settlementReceipt.InventTransCurrency_RU == inventTransCurrency)
                   // </GEERU>
                   && settlementReceipt.Cancelled       == 0
                   && settlementReceipt.QtySettled      >  0
            join forupdate
                #settlementFieldList from settlementIssue
                index hint TransactionIdx
                where settlementIssue.SettleTransId     == settlementReceipt.SettleTransId
                   && settlementIssue.SettleType        == InventSettleType::Issue
                   //+ sn 
                   //// <GEERU>
                   //&& (!countryRegion_RU || settlementReceipt.InventTransCurrency_RU == inventTransCurrency)
                   //// </GEERU>
                   && (!countryRegion_RU || settlementIssue.InventTransCurrency_RU == inventTransCurrency)
                   //- sn 
                   && settlementIssue.Cancelled         == 0
                   && settlementIssue.QtySettled        <  0
InventCostItemDimSecCur_RU\updateReceiptAdjustmentTrans

X++:
...
        if (adjustment &&
            (abs(adjustment) < inventClosing.MinTransferValue ||
             (_receipt.CostAmountSecCurAdjustment_RU - _adjustmentLater == 0 &&
             //+ sn
             // Currency::amount(_receipt.CostAmountSettledSecCur_RU / _receipt.QtySettled) == Currency::amount(costAmount / _receipt.QtySettled))))
              Currency::amount(_receipt.CostAmountSettledSecCur_RU / _receipt.QtySettledSecCur_RU, secondaryCurrency) == Currency::amount(costAmount / _receipt.QtySettledSecCur_RU, secondaryCurrency))))
             //- sn
...

            while select forceplaceholders pessimisticlock
                #settlementFieldList from settlementReceipt
                index hint RecIdTypeIdx
                where settlementReceipt.TransRecId              == _receipt.RecId
                   && settlementReceipt.SettleType              == InventSettleType::Receipt
                   && settlementReceipt.InventTransId           == _receipt.inventTransOrigin().InventTransId
                   && settlementReceipt.InventTransCurrency_RU  == inventTransCurrency
                   && settlementReceipt.Cancelled               == 0
                   && settlementReceipt.QtySettled              >  0
            join forupdate
                #settlementFieldList from settlementIssue
                index hint TransactionIdx
                where settlementIssue.SettleTransId             == settlementReceipt.SettleTransId
                   && settlementIssue.SettleType                == InventSettleType::Issue
                   //+ sn
                   //&& settlementReceipt.InventTransCurrency_RU  == inventTransCurrency
                   && settlementIssue.InventTransCurrency_RU    == inventTransCurrency
                   //- sn
                   && settlementIssue.Cancelled                 == 0
                   && settlementIssue.QtySettled                <  0
...

                //+ sn
                //settleValue = Currency::amount(settleValueDec, secondaryCurrency);
                //
                //if (abs(settleValueDec) < abs(settleValue))
                //{
                //    settleValue += (settleValueDec > 0 ? -roundOffunit : roundOffunit);
                //}
                if (abs(settleValueDec) > abs(roundOffunit))
                {
                    settleValue = Currency::amount(settleValueDec, secondaryCurrency);
                }
                else
                {
                    settleValue = sign(settleValueDec) * roundOffunit;
                }
                //- sn
InventCostItemDimSecCur_RU\updateItemReturnAdjustments()
X++:
public void updateItemReturnAdjustments(ItemId _itemId = inventCostList.ItemId)
{
...
this.updateTransKeyAdjust(); //sn
}
InventCostItemDimSecCur_RU\financialOpenValue
X++:
    //+ sn
    //CostAmount  costAmount = _inventTrans.isUpdatedFinancial() ? _inventTrans.financialOpenValueSecCur_RU() : _inventTrans.CostAmountSecCurPhysical_RU;
    CostAmount  costAmount = _inventTrans.isUpdatedFinancial() && _inventTrans.DateFinancial <= inventClosing.TransDate ? _inventTrans.financialOpenValueSecCur_RU() : _inventTrans.CostAmountSecCurPhysical_RU;
    //-sn
+ Разница InventSplitTrans и InventSplitTrans_Remain

Но самым интересным квестом оказался следующий :

1. Если у вас используется две модели по средней(для первичного и для вторичного), то когда вы запускаете вторичное закрытие виртуальный перенос по средней созданный в рамках первичного закрытия становится Нефинансовым (рвётся маркировка между лотами) со всеми вытекающими последствиями.

2. В результате такой ошибки при начислении НР за прошлые периоды все проводки зависают на средней и не корректируют связанные расходы.
__________________
Sergey Nefedov
Старый 10.11.2020, 17:36   #4  
Sergey Petrov is offline
Sergey Petrov
Участник
 
80 / 19 (1) ++
Регистрация: 03.04.2007
Адрес: Saint-Petersburg, Russia
Спасибо за помощь! Посмотрю ещё и в других местах. Вроде у нас проблемы только с указанными мной ранее, но мало ли...
__________________
MS Dynamics AX 2009

Kernel 5.0.1600.4110
Application 5.0.1500.6491
Старый 10.11.2020, 20:16   #5  
Pavel is offline
Pavel
SAP
SAP
 
2,760 / 239 (13) ++++++
Регистрация: 14.12.2001
Адрес: Moscow
Странно, что автор (один из) сего чуда присутствует на форуме, но скромно молчит.))
Старый 10.11.2020, 23:36   #6  
EVGL is offline
EVGL
Banned
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
4,445 / 3001 (0) ++++++++++
Регистрация: 09.07.2002
Адрес: Parndorf, AT
Цитата:
Сообщение от Pavel Посмотреть сообщение
Странно, что автор (один из) сего чуда присутствует на форуме, но скромно молчит.))
В мой огород камень? Когда нечего сказать, я молчу: амбиции разработчика я с себя сложил еще в 2008 году, ибо стало скучно. Ждем Microsoft с лучшим решением задачи. Слухи ходят, планы появляются: https://experience.dynamics.com/idea...0-00155d460d59

и исчезают, пока осталось только это: https://docs.microsoft.com/en-us/dyn...n-capabilities Если вчитаться, то это лишь доработка нового Учета затрат в D365 до уровня старого в AX2012, и результат в бухгалтерские книги не попадает.
Старый 10.11.2020, 23:48   #7  
EVGL is offline
EVGL
Banned
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
4,445 / 3001 (0) ++++++++++
Регистрация: 09.07.2002
Адрес: Parndorf, AT
P.S. Если поизучать сайт https://experience.dynamics.com/idea...4-000d3a4f1244 , то можно убедиться, что речь идет о третьем месте самых нужных функций для D365 в расчете себестоимости. В мире. Не в России. Причем Райнхард напрямую просит улучшить русскую фичу в том плане, чтобы было две и более модели для одной валюты, т.е. стандартная себестоимость в евро + средняя в евро. Так что стеб абсолютно неуместен.
Старый 11.11.2020, 15:56   #8  
Sergey Petrov is offline
Sergey Petrov
Участник
 
80 / 19 (1) ++
Регистрация: 03.04.2007
Адрес: Saint-Petersburg, Russia
Thumbs up
Коллеги, а что бы вы могли посоветовать, если у нас такое замечено только на паре номенклатур с типом "Услуга"? Откатывать закрытие склада до начала времён не хочется. Может, есть какие-то точечные инструменты?

Вот подумали и решили для начала просто пересчёт запустить. По идее, если там ничего не работало, то накопленные недосопоставленные суммы должны раскидаться.

В общем, пересчёт склада по отдельным позициям (причём, как во вторичной, так и в основной валютах) помог. Всё стало ровненько-красивенько.
__________________
MS Dynamics AX 2009

Kernel 5.0.1600.4110
Application 5.0.1500.6491

Последний раз редактировалось Sergey Petrov; 11.11.2020 в 17:04.
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Закрытие склада: обработка маркированных проводок Sergey Petrov DAX: Программирование 1 26.06.2015 12:04
Странное закрытие склада и коррекция себестоимости в наличии Aquarius DAX: Функционал 11 28.05.2010 11:45
Denis Fedotenko: Себестоимость и закрытие склада Blog bot DAX: База знаний и проекты 44 29.03.2010 14:54
Закрытие склада в валюте. NJD DAX: Функционал 1 05.10.2005 12:10
Закрытие склада в основной и вторичной валюте, отключенная корреспонденция счетов May DAX: Функционал 1 02.04.2004 13:25
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

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

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

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 11:45.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.