RSS

Stok hareketi üzerindeki rezervasyonu kaldırmak

Uzun süre sonra tekrar merhaba,

Bir geliştirme kapsamında transfer günlüğü satırlarını kullanarak işlem yapmak istiyorduk, fakat günlük satırlarındaki miktarlar ya sistem ya kullanıcı tarafından fiziksel veya siparişe göre rezerv edilmişti. Bizim geliştirmemizin ilerleyebilmesi adına varsa bu tür rezervasyonların günlük işleme başlamadan önce kaldırılması gerekiyordu.

Malumunuz üzere rezervasyon ile ilgili kodlar çok dallı budaklı ve karışık bir mahiyete sahiptir. Bende uzun süre uğraştıktan sonra tam ümidi keserken, Mr.Google da yazılmış bir kod öbeği buldum. Kod çok basit fakat inanılmaz derecede de doğru çalışıyordu. Onu biraz düzenledim ve aşağıdaki son halini verdim. Sizde olursa kendi ihtiyaçlarınıza göre uyarlayıp kullanabilirsiniz.

Güle güle kullanın.

// Changed on 22 May 2012 at 09:22:42 by etg_m
// Code is added to InventJournalTable methods
void removeAllJournalLinesReservation()
{

InventUpd_Reservation       res;
InventMovement              inventmovement;
Inventtrans                 inventtrans;
InventJournalTrans          inventJournalTrans
;
if(this.Posted)
return;

while select inventJournalTrans
index hint LineIdx
where inventJournalTrans.JournalId  == this.JournalId
{
while select inventTrans
index hint TransIdIdx
where inventTrans.InventTransId == inventJournalTrans.InventTransId
&&   (inventTrans.StatusIssue   == statusIssue::ReservOrdered ||
      inventTrans.StatusIssue   == statusIssue::ReservPhysical)
  {
   inventmovement  =   inventTrans.inventmovement(true);
   res =  InventUpd_Reservation::newInventDim(inventmovement,inventTrans.inventDim(),abs(inventTrans.Qty),true);
   res.updatenow();
  }
}
}

NOT: Yazıda belirtilen kodun, değiştirilmeden veya değiştirilerek, development/test/canlı ortamlarında kullanılması sonucu oluşabilecek olumlu/olumsuz durumlarda tüm sorumluluk kodu kullanan kişiye aittir.

Mesut BOZTAŞ

Dynamics AX ERP Danışmanı ve
İstanbul Ticaret Üni. Y.Lisans öğrencisi

İstanbul 2012

http://www.etg-it.com

 
Leave a comment

Posted by 22/05/2012 in 3S, Geliştirme

 

Etiketler: , , ,

İş akışlarında boş pozisyon değerlerinin atlanarak iş akışının bir sonraki pozisyona gönderilmesi

Merhaba,

İş akışlarında bugün karşılaştığım bir durumu ve buna uyguladğım çözümü paylaşmak istiyorum. Müşterimde iş akışlarında genel olarak hiyerarşi modeli kullanılmaktadır. Bu model ile iş akışında onay adımları kullanıcının durdurma kuralına göre uyuşan tüm üst seviyedeki yöneticileri için oluşmaktadır. Kullanıcının üst seviyedeki yöneticilerinden birisinin işten ayrılması sonucu ilgili pozisyon boş kalabilmekte ve iş akışlarında “pozisyon bulunamadı” ya da “kullanıcı bulunamadı” vb hatalar görülmektedir. Bu boş pozisyonun AX tarafından algılanmayıp bir sonraki pozisyondaki kullanıcıyı bulması için aşağıda adımları belirtilen değişiklikleri yaptım. Testlerim sonucu çalışıyor görünüyor.

1- AOT –> Classes –> WorkflowLimitHierarchyProvider

2- Yeni butonu ile aşağıdaki metodu ekledim.


// Changed on 10 Oca 2012 at 13:11:29 by mesut
// Eğer bir pozisyonda çalışan yoksa bir üst pozisyona bakar.
public HRPPartyPositionTableRelationship getNextPositionTable(HRPPartyPositionTableRelationship _positionTable)
{
HRPPartyPositionTableRelationship positionTable;

ValidFromDateTime _perDate = DateTimeUtil::getSystemDateTime();
;

if (_positionTable.RecId == 0)
{
throw error("@SYS119263"); // employee not found
}

select firstonly positionTable where positionTable.PositionId == _positionTable.ReportsToPosition
&& positionTable.hrmReferenceType == HRMVirtualNetworkReferenceType::Employee
&& positionTable.ValidFromDateTime <= _perDate
&& positionTable.ValidToDateTime   >= _perDate
&& positionTable.ReportsToPosition != "";

if (positionTable.RecId == 0)
{
throw error("@SYS119263"); // postion not found
}

if(positionTable.Reference)
return positionTable;
else
return this.getNextPositionTable(positionTable);
}

3 – WorkflowLimitHierarchyProvider.getNode() metodunda aşağıdaki eklemeyi yaptım.


private WorkflowLimitHierarchyProviderNode getNode(PositionId _position, WorkflowHierarchyLevel _level)
{
ExpressionDataSource nodeDataSource;
HRPLimitTableMap limitMapTable;
HRPLimitTypeTable limitTypeTable;
HRPPartyPositionTableRelationship positionTable;
HRPPartyJobTableRelationship jobTable;
userId user;
WorkflowHierarchyLevel level = _level + 1;
FromDateTime _perDate = DateTimeUtil::getSystemDateTime();
;

positionTable = HRPPartyPositionTableRelationship::find(_position);

// ETG MB start 10012012 ----------------------------> THIS SECTION WAS ADDED AS A NEW<-----------------------
if(!positionTable.Reference)
{
positionTable = this.getNextPositionTable(positionTable);
}
// ETG MB end ----------------------------> THIS SECTION WAS ADDED AS A NEW<-----------------------

if (positionTable.RecId == 0)
{
throw error("@SYS119263"); // position not found
}

if (positionTable.hrmReferenceType != HRMVirtualNetworkReferenceType::Employee)
{
throw error("@SYS120049"); // Employee Type not found
}

user = SysCompanyUserInfo::emplId2UserId(positionTable.Reference);
if (!user)
{
throw error("@SYS119264"); // user not found
}

jobTable = HRPPartyJobTableRelationship::find(positionTable.JobId);
if (jobTable.RecId == 0)
{
throw error("@SYS119262"); //job not found
}

nodeDataSource = ExpressionDataSource::newDataSourceValue(dataSource.parmName());
nodeDataSource.addField(ExpressionField::newFieldValue(#Workflow_PositionTitle, extendedtypestr(PersonTitle), positionTable.Title));
nodeDataSource.addField(ExpressionField::newFieldValue(#Workflow_JobTitle, extendedtypestr(PersonTitle), jobTable.Title));
nodeDataSource.addField(ExpressionField::newFieldValue(#Workflow_LineManagerLevel, extendedtypestr(WorkflowHierarchyLevel), level));

while select limitTypeTable
{
limitMapTable = HRPLimitTableRelationship::getActiveLimitEmpl(limitTypeTable.LimitId, positionTable.Reference);
nodeDataSource.addField(ExpressionField::newFieldValue(#Workflow_Limit + limitTypeTable.LimitId, extendedtypestr(HRPLimitValue), limitMapTable.LimitValue));
}

return WorkflowLimitHierarchyProviderNode::newProviderNode(
positionTable.Reference,
user,
level,
nodeDataSource);
}

NOT: Yazıda belirtilen kodun, değiştirilmeden veya değiştirilerek, development/test/canlı ortamlarında kullanılması sonucu oluşabilecek olumlu/olumsuz durumlarda tüm sorumluluk kodu kullanan kişiye aittir.

Mesut BOZTAŞ

Dynamics AX ERP Danışmanı ve
İstanbul Ticaret Üni. Y.Lisans öğrencisi

İstanbul 2012

http://www.etg-it.com

 

Etiketler: , , ,

Dynamics AX Favoriler menüsüne kod ile öğe eklenmesi

Merhaba,

Normal şartlar altında Favorilerim alanına almak istediğimiz menü öğesini sürekle bırakla yapabildiğimiz süreci bazı durumlarda kod/buton ile yapmamız gerektiğinde aşağıdaki kodu kullanabilirsiniz.

void addToFavorites()
{
#AOT
#define.ReportBuilderMenuItemName ("InventTable")

TreeNode            treeNode;
TreeNodeIterator    iterator;
TreeNode            myFavoritesNode;
     Menu                myFavoritesMenuNode;
;

// get the top level user node
treeNode = infolog.userNode();
if (!treeNode)
return;

// get the User Menu List which is the 1st child of the user node
     iterator = treeNode.AOTiterator();
treeNode = iterator.next();
if (!treeNode)
return;

// get the "My Favorites" node which is the 1st child of the User Menu List node
iterator = treeNode.AOTiterator();
     myFavoritesNode = iterator.next();
if (!myFavoritesNode)
return;

// find the "Report Builder" MenuItem
treeNode = TreeNode::findNode(#MenuItemsActionPath + #AOTDelimiter + #ReportBuilderMenuItemName);
     if (!treeNode)
return;

myFavoritesMenuNode = myFavoritesNode;
if (myFavoritesMenuNode)
{
myFavoritesMenuNode.addMenuitem(treeNode);
}
}

NOT: Yazıda belirtilen kodun, değiştirilmeden veya değiştirilerek, development/test/canlı ortamlarında kullanılması sonucu oluşabilecek olumlu/olumsuz durumlarda tüm sorumluluk kodu kullanan kişiye aittir.

Mesut BOZTAŞ

Dynamics AX ERP Danışmanı ve
İstanbul Ticaret Üni. Y.Lisans öğrencisi

İstanbul 2012

http://www.etg-it.com

 
Leave a comment

Posted by 10/01/2012 in Geliştirme

 

Etiketler: ,

Formlarda kendi kısayollarınızı oluşturmak

Merhaba,

Standart AX içinde buttonlara istediğiniz kısayolu vermek neredeyse imkansızdır. Burada ya AX’ın size verdiği alternatifi kullanmak zorundasınız (ALT+O gibi) veya değişikliğiniz çok sınırlı kalmaktadır. (ALT+O yerine ALT+K dönüştürmek gibi..) Buton kontorlü üzerinde bulunan KeyTip özelliğide bazen çaresiz kalabilmektedir. Örneğin F2 ve F3 tuşlarına basarak bir butona basılınca yapılan fonksiyonu tetiklemek mevcut geliştirme özellikleri ile pekte mümkün değildir.

Bunun için yapılması gereken aşağıdaki kodları sisteminizde uygun yerlere yazmak olacaktır. Sonrasından klavyedeki bütün butonlar emrinizde!
Öncelikle doğru butona basıldığının tespiti için USER32.DLL çağıran aşağıdaki metodu WINAPI sınıfına yeni bir metod olarak yapıştıralım.

static boolean getKeyPressed(int _keyCode)
{
    DLL winApiDLL = new DLL('USER32');
    DLLFunction getKeyState = new DLLFunction(winApiDLL, 'GetAsyncKeyState');
    int result;
    ;

    getKeyState.returns(ExtTypes::WORD);
    getKeyState.arg(ExtTypes::DWORD);

    result = getKeyState.call(_keyCode);

    if ((result & 0x8000) == 0x8000)
        return true;
    else
        return false;
}

Klavyedeki tuşlara karşılık gelen kodları http://msdn.microsoft.com/en-us/library/dd375731(VS.85).aspx

sitesinden bulabilirsiniz.

Buton kombinasyonunun kullanılacağı formunuzda aşağıdaki metodu oluşturun. Eğer kodu birden çok yerde kullanmayı planlıyorsanız DocuFileWatchDog classına kodu taşıyabilirsiniz.

<pre>void myKeyboardCheck()
{
    #define.F3(0x72)
    #define.timeOut(10)
    ;

    // Check if this form is the foreground window of Windows
    if (winApi::getForegroundWindow() == this.hWnd())
    {
        // Check if F3 is pressed
        if (WinApi::getKeyPressed(#ALT) && WinApi::getKeyPressed(#F3))
        {
            // Check if the button is enable
             if (MyVerySpecialButton.enabled())
            {
                MyVerySpecialButton.clicked();
            }
        }
    }
    // Reset timer
    this.setTimeOut('myKeyboardCheck', #timeOut, true);
}


Son olarakta Formun run metoduna aşağıdaki kodu yazmamız gerekmektedir. İlk satır tercihe bağlıdır.


MyVerySpecialButton.text(MyVerySpecialButton.labelText() +' (F3)');
this.myKeyboardCheck();

Global rezerveli tuşları görmek için \Application Documentation\Global\Shortcutkeys dizinini kontrol etmenizde fayda olacaktır.

NOT: Yazıda belirtilen kodun, değiştirilmeden veya değiştirilerek, development/test/canlı ortamlarında kullanılması sonucu oluşabilecek olumlu/olumsuz durumlarda tüm sorumluluk kodu kullanan kişiye aittir.

Mesut BOZTAŞ

Dynamics AX ERP Danışmanı ve
İstanbul Ticaret Üni. Y.Lisans öğrencisi

İstanbul 2011

http://www.etg-it.com

 
Leave a comment

Posted by 10/07/2011 in Geliştirme

 

Etiketler:

Dynamics AX memo türünde alanlarında arama yapmak

Merhaba,

Dynamics AX içinde Memo türünde olan string alanlarda arama/filtreleme yapmak imkansızdır. Fakat bu alandaki bir metni aramak zorundaysak bunun için bir yol var. AX içinde ilgili memo alanı için arama yapılamazken, ilgili tablonun ve alanın SQLdeki karşılığında AX içerisinden yazılacak bir kodla arama yapılabilir. Aramanın geri dönüş yapmak istediğiniz işleme göre değişebilir.

Aşağıdaki kod örneğinde gönderdiğim arama metine uyan satırların RECID değerleri bulunup geri dönderilmektedir.


// Changed on 09 Tem 2011 at 17:56:38 by mesut
//TABLENAME must be replaced by real table name contains Memo field.
public static server container searchText(TABLENAME _table,SearchString _searchText)
{
str                             sql;
Connection                      userConnection;
SqlStatementExecutePermission   permission;
Statement                       stmt;
ResultSet                       sqlres;
SqlSystem                       sqlSystem = new SqlSystem();
SysSQLSystemInfo                systemInfo =  SysSQLSystemInfo::construct();
container                       cRecId;
int                             i=1;
;

cRecId = conNull();
//Setup the connection needed to send the command to SQL Server.
userConnection = new Connection();
stmt = userConnection.createStatement();

//BP Deviation Documented
sql = "select RecId from [%1].[DBO].[%2] where %3 like '%%4%' and %5 = %6";

sql = strfmt(sql,
systemInfo.getloginDatabase(),
ReleaseUpdateDB::backendTableName(tablenum(TABLENAME)),
ReleaseUpdateDB::backendFieldName(tablenum(TABLENAME), fieldnum(TABLENAME,MEMOFIELDNAME)),
_searchText,
ReleaseUpdateDB::backendFieldName(tablenum(TABLENAME ), fieldnum(TABLENAME,MEMOFIELDNAME)),
sqlSystem.sqlLiteral(_table.DataAreaId));

//info(sql);
permission = new SqlStatementExecutePermission(sql);
permission.assert();

//BP Deviation Documented
sqlres = stmt.executeQuery(sql);

//Select queries record
while( sqlres.next())
{
cRecId = conIns(cRecId,i,sqlres.getInt64(1));
i++;
}
CodeAccessPermission::revertAssert();
return cRecId;

}

NOT: Yazıda belirtilen kodun, değiştirilmeden veya değiştirilerek, development/test/canlı ortamlarında kullanılması sonucu oluşabilecek olumlu/olumsuz durumlarda tüm sorumluluk kodu kullanan kişiye aittir.

Mesut BOZTAŞ

Dynamics AX ERP Danışmanı ve
İstanbul Ticaret Üni. Y.Lisans öğrencisi

İstanbul 2011

http://www.etg-it.com

 
Leave a comment

Posted by 10/07/2011 in Geliştirme

 

Etiketler:

 
Takip Et

Get every new post delivered to your Inbox.

Join 35 other followers