Blog Listem

27 Aralık 2011 Salı

AXAPTA runbase dialog

void clicked()
{
    Dialog      dialog;
    DialogField DEmplId;
    DialogField DApp;
    DialogField DAppDesc;
    ;

    dialog = new Dialog("@SYS108667");
    DApp     = dialog.addField(typeId(B_Approval));
    DAppDesc = dialog.addField(typeId(Description));
    DEmplId  = dialog.addField(typeId(EmplId));

    DApp.value(B_RepairJournalPartsChangeLines.Approval);
    DAppDesc.value(B_RepairJournalPartsChangeLines.ApprovalDescription);
    DEmplId.value(SysCompanyUserInfo::find(CurUserId()).EmplId);

    dialog.run(); // show

    if (dialog.closedOK())
    {
        ttsbegin;
        B_RepairJournalPartsChangeLines.Approval            = DApp.value();
        B_RepairJournalPartsChangeLines.ApprovalDescription = DAppDesc.value();
        B_RepairJournalPartsChangeLines.ApproveEmplId       = DEmplId.value();
        element.redraw();
        ttscommit;
    }
}
 
Not: AX 2012 ile birlikte kalkan typeId() yerine enumlar için enumStr(), diğer veri tipleri için extendedTypeStr() kullanılabilir.

AXAPTA stok transfer günlüğü post

    journalTableData        journalTabledata;
    inventJournalTable      inventJournalTable;
    InventJournalCheckPost  journalCheckPost;
    ;
    inventJournalTable = inventJournalTable::find(Line.InventJournalId);
    // Posting Journal
    journalTableData = JournalTableData::newTable(inventJournalTable);
    journalTableData.updateBlock(JournalBlockLevel::InUse,JournalBlockLevel::None);
    if (infolog.num(Exception::Error))
        return;
    infolog.clear(0);
    journalCheckPost =
    InventjournalCheckPost::newJournalCheckPost(JournalCheckPostType::Post,InventJournalTable);
    journalCheckPost.parmAutoBlock(true);
    journalCheckPost.run();
    if(journalTableData.hasErrors())
        return;

22 Aralık 2011 Perşembe

AXAPTA stok transfer günlüğü

Normalde formla çalışırken InventJournalName'yi seçiyoruz ve parametreler otomatik geliyor. Burda bu işlemi kendimiz yapıyoruz:

    InventJournalTrans  inventJournalTrans;
    InventJournalTable  inventJournalTable;
    InventJournalName   inventJournalName;
    InventDim toInventDim;
    InventDim tempInventDimTo;
    ;
    // Journal Header işle
    inventJournalName   = "MyJournalName"
    inventJournalTable.initValue();
    inventJournalTable.JournalId        = NumberSeq::newGetNum(InventParameters::numRefInventJournalId()).num();
    inventJournalTable.Description      = InventJournalName.Description;
    inventJournalTable.Reservation      = ItemReservation::Automatic;
    inventJournalTable.JournalType      = inventJournalType::Transfer;

    inventJournalTable.BlockUserGroupId     = inventJournalName.BlockUserGroupId;
    inventJournalTable.JournalNameId        = inventJournalName.JournalNameId;
    inventJournalTable.ApprUserGroup        = inventJournalName.ApprUserGroup;
    inventJournalTable.ApprFromSiteId       = inventJournalName.ApprFromSiteId;
    inventJournalTable.ApprFromLocationId   = inventJournalName.ApprFromLocationId;
    inventJournalTable.ApprFromWMSLocationId= inventJournalName.ApprFromWMSLocationId;
    inventJournalTable.ApprFromBatchId      = inventJournalName.ApprFromBatchId;
    inventJournalTable.ApprToSiteId         = inventJournalName.ApprToSiteId;
    inventJournalTable.ApprToLocationId     = inventJournalName.ApprToLocationId;
    inventJournalTable.ApprToWMSLocationId  = inventJournalName.ApprToWMSLocationId;
    inventJournalTable.ApprToBatchId        = inventJournalName.ApprToBatchId;
    inventJournalTable.VoucherSeqId         = inventJournalName.VoucherSeqId;

    inventJournalTable.insert();
toInventDim.clear();
toInventDim.initValue();
toInventDim.wMSLocationId = inventJournalName.ApprtoWMSLocationId;
toInventDim.InventLocationId = inventJournalName.ApprtoLocationId;
toInventDim.InventSiteId      = inventJournalName.ApprtoSiteId;

tempInventDimTo.clear();
tempInventDimTo = InventDim::findOrCreate(toInventDim);
    // journal lines işle
    inventJournalTrans.initValue();
    inventjournaltrans.initFromInventJournalTable(inventJournalTable);
    inventJournalTrans.Voucher      = NumberSeq::newGetNum(InventParameters::numRefInventJournalVoucherId()).num();
    inventJournalTrans.ItemId       = "MyItem001";
    InventJournalTrans.initFromInventTable(Inventtable::find(InventJournalTrans.ItemId));
    inventJournalTrans.TransDate    = systemDateGet();
    inventJournalTrans.Qty          = -1;
    inventJournalTrans.InventDimId = tempInventDimto.inventDimId;
    // rezervasyon kontrolü
    if (!InventMoveMent::setAutoReserving(InventJournalTrans))
    {
        inventJournalTable.delete();
        return;
    }
    inventJournalTrans.insert();

16 Aralık 2011 Cuma

AXAPTA Boş tarih atamak

Datetime değeri için:
myDateTime=DateTimeUtil::minValue();

Date değeri için:
myDate =global::dateNull();

6 Aralık 2011 Salı

5 Aralık 2011 Pazartesi

AXAPTA satış fiyatı, maliyet fiyatı

Satış fiyatı:
    B_RepairJournalOrderLines.ProjSalesPrice = InventTable::find(B_RepairJournalOrderLines.ItemId).LastUserPrice;
Maliyet fiyatı:
    B_RepairJournalOrderLines.ProjCostPrice = InventTableModule::find(B_RepairJournalOrderLines.ItemId,ModuleInventPurchSales::Sales).price() ;

29 Kasım 2011 Salı

AXAPTA Ana tablo formuna git çalışmayınca?

Bir tabloya bağlı kontrollerde tabloda ayarlanmışsa "Ana tablo formuna git" butonu otomatik olarak çalışır. Ancak kontrol sadece extended data tipine bağlıysa, çalışmaz. Bu durumda kendi Jumpref methodunuzu yazmanız gerekir.

Bu konuda Fatih Demirci'nin aşağıdaki kodundan faydalandım:

public void jumpRef()
{
EmplTable emplTable;
Args args;
MenuFunction menuFunction;
;
emplTable = EmplTable::find(this.text());
if (!emplTable)
{
return;
}
args = new Args();
args.caller(element);
args.record(emplTable);
menuFunction = new MenuFunction( menuitemdisplaystr(EmplTable),
MenuItemType::Display);
menuFunction.run(args);
}

Ancak bu kodun standart "Ana tablo formuna git" butonundan ufak bir farklılığı vardı. Ekrana sadece ilgili kaydı getiriyordu. Standarttaysa ilgili kayıt bulunuyor ve tüm kayıtlar görüntüleniyordu. Ufak bir araştırma sonrası aşağıdaki kodu yazdım. Tam standarttaki gibi çalışıyor:

public void jumpRef()
{
CustTable custTable;
Args args;
MenuFunction menuFunction;
;
args = new Args();
args.caller(element);
args.lookupfield(FieldNum(CustTable,AccountNum));
args.lookupValue(this.text());
menuFunction = new MenuFunction(MenuItemDisplayStr(custTable),MenuItemType::Display);
menuFunction.run(args);
}

24 Kasım 2011 Perşembe

AXAPTA Kullanıcı ilişkileri

Axapta'da kullanıcı ilişkileriyle ilgili üç tablo var:

UserInfo - Bu tabloda Axapta'ya girebilmek için kullandığınız active directory user kodları var:
Id alanında user id ve name alanında ismi ...

EmplTable - Bu personel dosyası.
EmplId alanında personel kodu var.

SysCompanyUserInfo - Bu tablo UserInfo ve EmplTable dosyalarını birbirine bağlamaya yarıyor. Bu tablodaki UserId alanına UserInfo tablosundaki Id ve EmplId alanına da EmplTable'daki EmplId bilgisi atılarak aradaki bağlantı sağlanıyor. Bu bağlantıyı yapmak için Yönetim->Kullanıcı ilişkileri formunu kullanabilirsiniz.

Mevcut ID alanını CurUserId() fonksiyonu ile alabilirsiniz.
Mesela bir tablo oluşturdunuz ve o tabloda sisteme giriş yapılan varsayılan Employee ID değerini atamak istiyorsunuz:
    MyTable.EmplId = SysCompanyUserInfo::find(CurUserId()).EmplId;

3 Kasım 2011 Perşembe

AXAPTA'yı çökertmek: hata 174

Aşağıdaki kod hata vermiyor. Ancak istediğim işi de yapmayacak, yine de hata 174 verip AOS'u göçertmemesi gerekir:

    select firstonly * from ord join rel join obj
        where ord.ServiceOrderId == rel.RelKeyId &&
            rel.RelTableId == ord.TableId &&
            obj.ServiceObjectId == rel.ServiceObjectId &&
            ( L_ItemSerialNum.valueStr()== obj.ItemSerialNum || (!L_ItemSerialNum)) &&
            ( L_SMAServiceObjectId.valueStr()== rel.ServiceObjectId || (!L_SMAServiceObjectId));

Kodu düzeltince hata vermiyor:
    select firstonly * from ord join rel join obj
        where ord.ServiceOrderId == rel.RelKeyId &&
            rel.RelTableId == ord.TableId &&
            obj.ServiceObjectId == rel.ServiceObjectId &&
            ( L_ItemSerialNum.valueStr()== obj.ItemSerialNum || (!L_ItemSerialNum.valueStr())) &&
            ( L_SMAServiceObjectId.valueStr()== rel.ServiceObjectId || (!L_SMAServiceObjectId.valueStr()));

İnternette ufak bir araştırma yaptım ve bu hatanın tamamen düzgün yazılmış kodlarda da verdiğini öğrendim.

27 Ekim 2011 Perşembe

AXAPTA Number Sequence, numara almanın başka bir yolu

    ExtendedTypeId              id  = TypeID2ExtendedTypeId(TypeId(SMAServiceObjectId));
    NumberSeq                   num = NumberSeq::newGetNum(NumberSequenceReference::find(id));
    ;
...
...
    SMAServiceObjectTable.ServiceObjectId     = num.num();

26 Ekim 2011 Çarşamba

AXAPTA Form datasource içinde kullanılan bir tablo alanını kodla kontrol.

Dizayn ekranında bu çok kolay. Kodla yapmak için object dizisini kullanmak gerekiyor:    

SMAObjectGroup_ds.object(fieldnum(SMAServiceObjectGroup,
        Barebone)).enabled(SMAObjectGroup.ServiceItemType == B_ServiceItemType::Item);

20 Ekim 2011 Perşembe

AXAPTA Yeni kaydı başka bir formda yapıp asıl forma geri dönmek

Bazı durumlarda Yeni kaydı başka bir formda yapmak isteyebilirsiniz veya bunu yapmak zorunda kalabilirsiniz. Axapta orjinal formlarında bunun örnekleri var ancak doğrusu bana çok karışık geldi. Ben basitçe şöyle yaptım:
Ana formun Create methodu:

public void create(boolean _append = false)
{
    Args                args;
    FormRun             formCreate;
    ;

        args = new Args();
        args.name(formstr(B_ExpressServiceNew));
        args.caller(element);

        formCreate = classfactory.formRunClass(args);
        formCreate.init();
        formCreate.run();
        formCreate.wait();
}

Buradaki B_ExpressServiceNew, bizim kayıt açan formumuz oluyor.
Kayıt açan formdaki kayıt methodunun bizi ilgilendiren parçası :


    if (element.args() && element.args().caller() && element.args().caller().name() == formstr(B_ExpressService))

    {
     mainForm = element.args().caller();
     mainForm.SetRecord(oTable);
    }


B_ExpressService ana formumuz, oTable da kaydımız.
Bu da yeni oluşturduğumuz kayda konumlanabilmek için ana formda açtığımız setrecord methodu:

void SetRecord(SMAServiceOrderTable _order)
{
    ;
    SMAServiceOrderTable.reread();
    SMAServiceOrderTable.data(_order);
    SMAServiceOrderTable_DS.setCurrent();

} 

AXAPTA Edit method örneği:

Edit method, tabloda bir field'ın değerinin tabloda bulunmayan başka bir bilgiye göre güncellendiği zaman kullanılabiliyor. Mesela burda tablonun ServiceObjectId alanı ItemId'ye göre değişiyor. Editmethod'a tablodaki ServiceObjectId değerine sahip ItemId değerini getiriyoruz, ve ItemId değiştikçe tablodaki ServiceObjectId alanını güncelliyoruz.


edit ItemId EditItemId(boolean set, ItemId _ItemId)
{
    ItemId ret;
    ;

    if (set)
    {
        this.ServiceObjectId =
            SMAServiceObjectTable::findItem(_ItemId).ServiceObjectId;
    }
    else
    {
        ret = SMAServiceObjectTable::find(this.ServiceObjectId).ItemId;
    }
    return ret;
}

Set boolean değeri editmethod'un düzenleme mi yoksa görüntüleme için mi çalışacağını belirliyor. Set true ise ikinci parametre (burada _ItemId) kullanıcı tarafından doldurulmuş demektir. aşağıda bu duruma göre ilgili field dolduruluyor. False olduğu zaman da ilgili field bilgisinden editmethod değeri geliyor.

13 Ekim 2011 Perşembe

AXAPTA Splitter Kontrol

Axapta gerçek bir splitter kontrole sahip değil. Grup paneliyle bir class yapılmış ve bu birleştirilmiş. Axapta içinde bunu kullanan bazı formlar var. İsteyen oradan da bakabilir.
ClassDeclaration'a aşağıdaki kodlar yazılıyor:

    SysFormSplitter_X               _VerticalSplitter;
    SysFormSplitter_Y               _HorizontalSplitter;



Birincisi dikey splitter için, ikincisi ise yatay. Aşağıdaki kodu da formun init'ine yazıyoruz:

   _VerticalSplitter = new SysFormSplitter_X(VerticalSplitter,groupLeft,element);
   _HorizontalSplitter = new SysFormSplitter_Y(HorizontalSplitter,groupTop,element);

Dikey Splitter İçin Ayarlar:
Yukarıdaki VerticalSplitter, dikey splitter kontrol için kullandığımız Group kontrolü. Group kontrolün değerlerini aşağıdaki gibi ayarlıyoruz:
AlignChild = No
AlignControl = Yes
AutoDeclaration = Yes
BackgroundColor = Window background
FrameType = Raised 3D
HideifEmpty = No
Height = Column height
Width = 5
Dikey splitter'in sağına ve soluna birer group kontrol koyuyoruz ve parent kontrolünü de 3 column olarak ayarlıyoruz. Eğer buraya dikkat etmezsek ekran tuhaf birşey olur çıkar. Soldaki grubu Autodeclaration = Yes yapıyoruz. Soldaki grubun adı yukarıdaki groupLeft oluyor. Height değerini Column Height yapıyoruz, Width değerini de 100-200 gibi birşey ayarlıyoruz, bu değer zaten biz kaydırdıkça değişecek ve saklanacak. Sağdaki grubun height değerini column height ve width değerini de column width olarak ayarlıyoruz, başka bir ayar gerekmiyor burası için.
Dikey splitter'in methodlarını da aşağıdaki gibi ayarlıyoruz:

int mouseUp(int x, int y, int button, boolean ctrl, boolean shift)
{
    int ret;

    ret = super(x, y, button, ctrl, shift);

    Return _VerticalSplitter.mouseUp(x, y, button, ctrl, shift);
}

int mouseMove(int x, int y, int button, boolean ctrl, boolean shift)
{
    int ret;

    ret = super(x, y, button, ctrl, shift);

    Return _VerticalSplitter.mouseMove(x,y,button,ctrl,shift);
}

int mouseDown(int x, int y, int button, boolean ctrl, boolean shift)
{
    int ret;

    ret = super(x, y, button, ctrl, shift);

    Return _VerticalSplitter.mouseDown(x, y, button, ctrl, shift);
}

Yatay Splitter İçin Ayarlar:
Burada sadece dikeyden farklı olanları anlatacağım. Yatay'ın farklı ayarları:
Parent kontrolde columns = 1 olacak.
Height = 5
Width =Column Width
Örneğimizdeki üstündeki grubun adı groupTOP. Farklı olarak Height değeri 100-200 gibi birşey ve Width değeri Column width. Methodlarına da yukarıdakinden farklı olarak _VerticalSplitter yerine _HorizontalSplitter yazılacak. Altta kalan grubun Width değeri Column Width ve Height değeri de Column Height olacak.


Hepsi bu. Bana ilk incelediğimde çok karışık gelmişti, ancak formdan ayıklayınca ve biraz kurcalayınca aslında basit birşey olduğunu gördüm.
 

12 Ekim 2011 Çarşamba

AXAPTA Forma sürüklenen tablo field grubunu edit edebilmek?

Yeni alan ekleyebilmek için grubun AutoDataGroup özelliğini No yapmak ve gerekiyor.
Değişiklik veya silmek yapabilmek için de DataGroup alanını boşaltmak gerekiyor.

6 Ekim 2011 Perşembe

AXAPTA Adres tablosuyla çalışmak

Daha doğrusu adres tablolarıyla demek lazım. Birkaç tabloyu join ile birleştirmek gerekiyor. Benim örneğimde VendTable daki bir satıcının adres bilgilerini almaya çalışacağız:

    DirPartyAddressRelationShip         dirPartyAddressRelationShip;
    DirPartyAddressRelationShipMapping  dirPartyAddressRelationShipMapping;
    Address                             address;
    ;
                    select firstonly * from DirPartyAddressRelationShip join
                        dirPartyAddressRelationShipMapping join address
                        order by
                            DirPartyAddressRelationShip.Shared desc,
                            DirPartyAddressRelationShip.IsPrimary desc
                        where DirPartyAddressRelationShip.PartyId == VendTable::find(vendPAckingSlipJour.OrderAccount).PartyId &&
                              dirPartyAddressRelationShipMapping.PartyAddressRelationshipRecId == dirPartyAddressRelationShip.RecId &&
                              address.RecId == dirPartyAddressRelationShipMapping.AddressRecId &&
                              address.type == AddressType::Service;

DirPartyAddressRelationShip tablosu adreslerle kaynak tablo (buradaki örnekte VendTable) arasındaki bağlantıları sağlayan tablo. Örnekteki VendTable tablosundaki PartyId alanıyla DirPartyAddressRelationShip tablosu bağlanıyor.
Adreslerse Address tablosunda. DirPartyAddressRelationShip ve Address tablosunu birbirine bağlayan tabloysa DirPartyAddressRelationShipMapping tablosu. DirPartyAddressRelationShipMapping tablosunun PartyAddressRelationshipRecId alanıyla DirPartyAddressRelationShip tablosunun RecId alanı birbirine bağlanıyor. 
DirPartyAddressRelationShipMapping tablosunun AddressRecId alanıyla da Address tablosunun RecId alanı birbirine bağlanıyor ve bağlantı tamamlanmış oluyor. 

DirPartyAddressRelationShip tablosundaki Shared alanı Satıcılar formundaki Adres tabındaki Genel alanına, IsPrimary alanı da Birincil alanına denk geliyor. Type alanı da adres türlerine denk geliyor. Ben burada servis adresini almak istediğim için bu alanı AddressType::Service enum değerine eşitledim.

5 Ekim 2011 Çarşamba

AXAPTA icase karşılığı ve bugünün tarihi

b = a > SystemDateGet() ? "büyük" : "küçük"

AXAPTA TC Kimlikno extended data tipi var mı?

Evet bu alan hazır var, açmaya gerek yok. Adı IdentityNum_TR . Ancak bu alanı biraz hatalı açmışlar. Bu alanın boyu 11 karakter olmalıydı. 12 karakter açılmış.

30 Eylül 2011 Cuma

AXAPTA Kayıtları Tazeleme

    repairjournal_ds.research();
    repairjournal_ds.refresh();

eğer cursor aynı kayıtta kalsın isteniyorsa:

    repairjournal_ds.research(true);
    repairjournal_ds.refresh();

AXAPTA Boş InventDimID verme

Boş inventdimid verme kodu:

SMAServiceBOMTable.InventDimId  = InventDim::inventDimIdBlank();

29 Eylül 2011 Perşembe

AXAPTA Query: Boş kayıtlar, boş olmayan kayıtlar

Query Addrange methodunda value değerine = yerine farklı işaretler koymak istersek değeri tırnak içinde formatlandırmak gerekiyor. Ama bazı durumlarda bu gereksiz:

Boş olmayanları istiyorsak:
    qbds.addRange(fieldnum(custtable,name)).value(sysquery::valueNotEmptyString()) ;
Boş olanları istiyorsak:
    qbds.addRange(fieldnum(custtable,name)).value(sysquery::valueEmptyString()) ;
10000 olmayanları istiyorsak:
    qbds.addRange(fieldnum(custtable,accountnum)).value(sysquery::valueNot("10000") ) ;
Aralık:
    qbds.addRange(fieldnum(custtable,accountnum)).value(queryrange("1","10000") ) ;
Enum:
            qbds.addRange(fieldnum(B_RMARequestTable, RefType)).value(queryvalue(B_RMAReqRefType::RepairJournal));


AXAPTA Kodla kayıt eklerken numara serisi

Dün eksik bıraktığım bir madde vardı. Kodla kayıt eklerken nasıl numara verilir?

B_RepairJournalPartsChange.ChangeNo               = NumberSeq::newGetNum(SMAParameters:: numRefRMARequestNo()).num();

28 Eylül 2011 Çarşamba

AXAPTA A'dan Z'ye numara serisi oluşturma

İlk önce hangi modül için numara serisi oluşturacaksak onun tablosu ve class'ını öğreniyoruz.
Benimkinin tablosu SMAParameters (Modülün parametreler ekranında kurulumdan öğrenilebilir ). Aşağıdaki methodu tablonun methodlarına ekliyoruz:

public server static NumberSequenceReference numRefRMARequestNo()
{
    return NumberSeqReference::findReference(
            typeid2extendedtypeid(typeid(B_RMARequestNo)));
}

AX 2012 için güncelleme:

typeid2extendedtypeid(typeid(B_RMARequestNo))

yerine

extendedTypeNum(SNBmasterNum) 

yazmalısınız.

Buradaki "B_RMARequestNo" tablomuzdaki anahtar alanın extended data tipi oluyor.

Ardından classa gidiyoruz. İlgili sınıfının adı parametre tablosunun numberSeqModule metodundan öğrenilebilir. Benimki NumberSeqReference_SMA. loadModule methoduna aşağıdaki kodu ekliyoruz:

    /* RMA Request No */
    numRef.DataTypeId              = typeId2ExtendedTypeId(typeid(B_RMARequestNo));
    numRef.ConfigurationKeyId      = configurationkeynum(SMAManagement);
    numRef.ReferenceHelp           = literalstr("Benim Numaram");
    numRef.WizardContinuous        = false;
    numRef.WizardFetchAheadQty     = 20;
    numRef.WizardManual            = NoYes::No;
    numRef.WizardAllowChangeDown   = NoYes::No;
    numRef.WizardAllowChangeUp     = NoYes::No;
    numRef.SortField               = 11;
    this.create(numRef);

Sortfield alanına bir üstteki tanımlanmış numberseqin bir fazlasını veriyoruz. Hiç yoksa 1.

AX 2012 için güncelleme:
Sihirbazı çalıştırmadan önce ya AOS restart ya da aşağıdaki komutu çalıştırın:

NumberSeqApplicationModule::loadAll();


Sonra Temel->Kurulum->Numara serileri->Numara serileri'ne (AX 2012 için Organizasyon yönetimi->Ortak->Numara serileri->Üret) giriyoruz. Burda da sihirbazı çalıştırıyoruz.
Kontrol etmek için ilgili modülünü servis parametrelerinden numara serileri tabına gidip bir göz atıyoruz.

Sıra bu numara serisini formda kullanmakta:

Form classDeclaration a bu satırı ekleyin:

NumberSeqFormHandler numberSeqFormHandler;

Forma bu methodu ekleyin:

NumberSeqFormHandler numberSeqFormHandler()
{
    ;
    if (!numberSeqFormHandler)
    {

        numberSeqFormHandler = NumberSeqFormHandler::newForm(SMAParameters::numRefRMARequestNo().NumberSequence,
                                                             element,
                                                             B_RMARequestTable_DS,
                                                             fieldnum(B_RMARequestTable,RequestNo));
    }
    return numberSeqFormHandler;
}

Güncelleme: Yukarıdaki satır AX 2012 için şöyle olacak:
numRefRMARequestNo().NumberSequence
yerine
numRefRMARequestNo().NumberSequenceId 

B_RMARequestTable_DS sizin tablonuzun Datasourcesi. RequestNo da anahtar field.

Form close method:

public void close()
{
    if (numberSeqFormHandler)
    {
        numberSeqFormHandler.formMethodClose();
    }
    super();
}

Data source methodlarında yapılacaklar:

public void linkActive()
{
    ;
    element.numberSeqFormHandler().formMethodDataSourceLinkActive();
    super();
}

public boolean validateWrite()
{
    boolean ret;

    ret = super();
    ret = element.numberSeqFormHandler().formMethodDataSourceValidateWrite(ret) && ret;

    return ret;
}

public void write()
{
    super();
    element.numberSeqFormHandler().formMethodDataSourceWrite();
}

public void delete()
{
    ttsbegin;
    element.numberSeqFormHandler().formMethodDataSourceDelete();
    super();
    ttscommit;
}

public void create(boolean _append = false,boolean extern = false)
{
    element.numberSeqFormHandler().formMethodDataSourceCreatePre();
    super(_append);
    if (!extern)
    {
        element.numberSeqFormHandler().formMethodDataSourceCreate();
    }
}

Hepsi bu kadar...

20 Eylül 2011 Salı

AXAPTA Bir ürünün birimi

Ürün birimleri direk ürün tablosuna kaydedilmiyor. Ayrı bir tabloda saklanıyor:

MyTable.UnitID  = InventTableModule::find(Sobj.ItemId,ModuleInventPurchSales::Invent).UnitId;


2. parametreden hangi modülün birimini istediğimizi veriyoruz.

14 Eylül 2011 Çarşamba

AXAPTA Numaratör

Axapta'da tablolarda numaratör için "Number Sequence" var. Ancak sadece bir string içindeki değeri numara olarak arttırmak isterseniz? Yani "AB0001"->"AB0002" gibi. Bunun için hazır bir fonksiyon ya da bir kod bulamadım ve şunu yazdım:

Static str AutoNum(str Num)
{
    int i;
    int bas;
    str b;
    ;
    for (i=StrLen(num);i>=1;i--)
    {
        b=SubStr(num,i,1);
        if (b<"0" || b>"9")
        {
            bas=i+1;
            Break;
        }
        if (i==1)
            bas=1;
    }
    num=StrReplace(SubStr(num,1,bas-1)+
    Num2Str(Str2Num( SubStr(num,bas,StrLen(num) - bas + 1) )+1,
        StrLen(num) - bas + 1,0,1,0)," ","0");
    Return num;
}

6 Eylül 2011 Salı

AXAPTA Modified methodu bazen iki kez çalışıyor

Combobox değeri lookup ile seçilirse ve modified methodu içinde data source yenileme yapılırsa modified method'u iki defa çağrılıyor. Aynı durumla bir kişi daha karşılaşmış ve malesef sorusuna bir cevap alamamış.
public void modified()
{
    ;
    super();
    info("111");
    salesLine_DS.research(true);
    salesLine_DS.refresh();
    info("222");
}
Benzer durumla ilgili bir sayfa daha buldum ve oradaki çözümü kendime uyguladım. Class declaration methoduna bir kontrol değişkeni tanımladım ve:

public void modified()
{
    ;
    super();
    if (hasChanged) //çift çağırma bugını gidermek için.
        return;
    hasChanged=true;
    info("111");
    salesLine_DS.research(true);
    salesLine_DS.refresh();
    hasChanged=false;
    info("222");
}

24 Ağustos 2011 Çarşamba

AXAPTA Çoklu tablo ile lookup

SysTableLookup sınıfını kullanarak Axapta'nın kendi lookupunu ezip kendimize özel lookup yazabiliyoruz ve iki tabloyu birleştirebiliyoruz. Peki lookup ekranında 2. tablodan bir field göstermek istersek? Axapta standart SysTableLookup sınıfı bunu sağlamıyor. Ancak SysTableLookup'tan türetilmiş ve bunu sağlayan bir class var: SysMultiTableLookup.

Verdiğim linkten indirip kolayca kullanabilirsiniz. Aşağıda bir örnek kullanmını da verdim:


public void Agreementlookup(FormControl _formControl, str _filterStr)
{
SMAAgreementTable SMAagreementTable;
Query query = new Query();
SysMultiTableLookup sysTableLookup;
QueryBuildDataSource queryBuildDataSource = query.addDataSource(tablenum(SMAAgreementTable));
QueryBuildDataSource qbds2;
QueryBuildRange qbr;
;

qbds2=queryBuildDataSource.addDataSource(tablenum(B_AgreementCustomerTable));
qbds2.relations(true);

qbr=qbds2.addRange(fieldnum(B_AgreementCustomerTable, num));

qbr.value(strfmt('((Num == "%1") && (AccountCode == TableGroupAll::Table)) || (AccountCode == TableGroupAll::All)',
QueryValue(salesTable.CustAccount)));

sysTableLookup = SysMultiTableLookup::newParameters(_formControl,query);
sysTableLookup.addLookupfield(fieldnum(SMAAgreementTable, AgreementId),1);
sysTableLookup.addLookupfield(fieldnum(SMAAgreementTable, AgreementDescription),1);
sysTableLookup.addLookupfield(fieldnum(SMAAgreementTable, ProjId),1);
sysTableLookup.addLookupfield(fieldnum(B_AgreementCustomerTable, AccountCode),2);
sysTableLookup.addLookupfield(fieldnum(B_AgreementCustomerTable, Num),2);

sysTableLookup.parmQuery(query);
sysTableLookup.performFormLookup();
}

22 Ağustos 2011 Pazartesi

AXAPTA İlk bug

Bugün AXAPTA'da ilk bug'ımı keşfettim:

classDeclaration metodum aşağıdaki gibi olunca görünen hatayı  veriyor:
public class FormRun extends ObjectRun
{
    FormStringControl       lineAccountField;
    FormStringControl       lineAccountField2;
    NumberSeqFormHandler    numberSeqFormHandler;
    SMAAgreementId          agreementId;
}



Bu şekilde yazarsam hata filan yok:
public class FormRun extends ObjectRun
{
    FormStringControl       lineAccountField;
    NumberSeqFormHandler    numberSeqFormHandler;
    SMAAgreementId          agreementId;
    FormStringControl       lineAccountField2;
}





18 Ağustos 2011 Perşembe

AXAPTA "Ana tablo formuna git" kısayoluyla gönderilen değer

Bu değere args().record() metoduyla ulaşılabiliyor, ancak farklı farklı tablolardan farklı alan isimleriyle extend edilmiş değerler olunca switch case koymak pek te iyi bir çözüm değil.

FormStringControl   callerControl   = SysTableLookup::getCallerStringControl(element.args());
;
info(callercontrol.text());

Kod satırını Yakup Kirişçi'nin blogundan buldum. Standart lookup formlarında bulunan bir kodmuş. Benim çok işime yaradı. Kendisine teşekkürler...