Bu sayede XPO'larımız versiyon kontrollü olmuş oluyor. Yedekleme açısından çok faydalı olan aşağıdaki kodu Eren Polat'dan aldım.
SysExportDialog formunun metodlarına aşağıdaki kodları ekleyin:
classDeclaration:
str sDate, sTime, sDateTime;
str sMilliSeconds;
init:
sMilliSeconds = int2str(winApi::getTickCount());
sDate = int2str(year(today())) + strReplace(num2str(mthofyr(today()),2,0,0,0), ' ', '0') + strReplace(num2str(dayofmth(today()),2,0,0,0), ' ', '0');
sTime = strfmt("%1:%2", time2str(timeNow(),1,1), substr(sMilliSeconds, strlen(sMilliSeconds)-2,2));
sTime = strReplace(sTime,":","");
sDateTime = strfmt("_%1%2",sDate,sTime);
run:
//element.updateBox(fileNameNext(strfmt('%1%2_%3%4', filePath, preFix, treeNode.treeNodeName(), #xpo)));
element.updateBox(fileNameNext(strfmt('%1%2_%3%4%5', filePath, preFix, treeNode.treeNodeName(), sDateTime, #xpo)));
Blog Listem
23 Aralık 2015 Çarşamba
22 Aralık 2015 Salı
AX 2012 - Yeni WMS el terminali geliştirme
Microsoft kendi geliştirdiği WMS-II çözümünü bırakıp başka bir firmadan satın aldığı WMS çözümünü AX içine koydu. Bu yeni WMS çözümünün web ortamında çalışan kendine ait bir el terminali çözümü de var. El terminali çözümü tamamen web ortamında çalışırken geliştirme yaparken AX içinden çalıştırılması da sağlanmış. WHSWorkExecute isimli menu item ile AX tarafında bu çözümü çalıştırabiliriz. Microsoft WMS ve TM için ayrıntılı birer klavuz yayınlamış. WMS klavuzunda el terminali için kullanıcı tanımlama ve ayarlarını yapma anlatılmış. Ben bunları geçerek direk konuya giriyorum.
Klavuzda geliştirme hakkında bir bilgi yok. Ben bu konuda bulduğum bir blogdan faydalandım. Kendim uğraşsam bulamayacağımı sandığım püf noktalarını da hiçbir çaba sarfetmeden bu blogdan öğrenmiş oldum. :)
El terminali geliştirme yöntemini anlatırken WMS dökümanında anlatılan konuları bildiğinizi farzedeceğim.
El terminali geliştirmesi tamamen X++ classlar üzerinden çalışıyor. Yaptığınız her yeni menu item için bir class oluyor. Tüm menu item classları WMSWorkExecuteDisplay ile başlıyor.
Kendi menu itemimizi geliştirdiğimizi farzedelim. Eğer kendi menu itemimizi geliştirmeyeceksek bu adımı atlayabiliriz:
Yeni bir work ve/veya indirect menu item ekleyeceğiniz zaman WHSWorkCreationProcess enumuna bunu yeni bir eleman olarak eklemelisiniz. Eğer eklediğiniz menu item bir work ise ayrıca WHSWorkExecuteMode enum içine de eklemeniz gerekiyor. Okuduğum blogda yazdığına göre WHSWorkExecuteMode içine eklediğiniz elemanın adı ve label içeriği WHSWorkCreationProcess içine eklediğiniz ile birebir aynı olmalıymış, ben bunu hiç test etmedim, aynen söylenene uydum. Bizim elemanın adı Test olsun.
Bizim sınıfın adının WMSWorkExecuteDisplayTest olduğunu farzedelim. Sınıfımız WHSWorkExecuteDisplay sınıfından türeyecek.
Yukarıda anlattığımız enumlara eklenen eleman sayesinde kullanıcıya menu item tanımlama ekranında (Mobile device menu items ->Genel->Work creation process) yeni bir menu item daha görülebilecek. Ancak onun çağrılabilmesini sağlamak için yapılması gereken birşey daha var; WHSWorkExecuteDisplay sınıfının construct metodundaki switch/case bloğuna aşağıdaki kod parçasını eklemek:
case WHSWorkExecuteMode::MyTest : return WHSWorkExecuteDisplayTest::construct();
El terminali geliştirmesindeki tüm menu itemler kendi sınıfları içindeki displayForm metodu vasıtasıyla çalışıyor. Ben mevcut sınıflardan birini alıp kopyaladım ve onun üzerinde yaptığım değişikliklerle işimi gördüm. displayForm metodu aşamalar şeklinde çalışıyor. Bunu step isimli değişkenle takip ediyor. birinci aşama sıfır. Benim kopyaladığım sınıfta son aşama 2 olan kayıt aşamasıydı. Aşamaları orijinal sınıflarda da yapıldığı gibi displayForm metodunda bir switch/case ile takip edebilirsiniz.
Web formumuza yeni bir kontrol eklemek için buildControl metodunu kullanıyoruz:
ret += [this.buildControl(#RFText, #vendor, "@SYS14048", 1, pass.lookup(#vendor), extendedTypeNum(VendAccount), '', 0,false)];
Yukarıdaki kontroldeki #vendor makrosu WHSRF makrosunda yoksa bizim bunu ayrıca eklememiz gerekiyor. Yine blogdan öğrendiğim üzere bu metodun parametreleri şöyle (ordan copy/paste yapıp türkçeye çevirdim sadece):
Kontrolde kullandığımız datanın map edilip edilmediğini öğrenmek için exists, edilmişse de değerini öğrenmek için lookup metodlarını kullanıyoruz. Genelde aşağıdaki şekilde kullanılıyor:
if (pass.exists(#vendor) && pass.lookup(#vendor) != '")
Data değerini eklemek/değiştirmek için insert metodunu kullanıyoruz:
pass.insert(#vendor,purchTable.OrderAccount);
Bu arada Mobile device menu items formunda diğer menu itemlerinde gözüken ancak sizinkinde gözükmeyen seçenekleri görmek istiyorsanız bunun için (daire içinde işaretlediklerim)
WHSRFMenuItem formunun togglefields metodunda ufak bir değişiklik gerekiyor:
if (whsrfMenuItemTable.WorkCreationProcess == WHSWorkCreationProcess::PurchaseOrderItemReceiving ||
whsrfMenuItemTable.WorkCreationProcess ==
...
...
//memre 22.12.2015
whsrfMenuItemTable.WorkCreationProcess == WHSWorkCreationProcess::PurchaseOrderLineReceivingWithVendor)
//memre
...
...
Aynı zamanda WHSRFControlData sınıfının processControl metodunda ekstra güncellemeler yapmanız gerekebilir. Benim yaptığım bir geliştirmede orijinalinden kopyaladığım sınıfta orijinalinde LP (License Plate) oluşurken benimkinde oluşmuyordu. Sebebiyse enum ile yapılan LP kontrolüydü. Benim için aşağıdaki güncelleme iş gördü:
case #LicensePlateId:
...
...
else if (mode != WHSWorkExecuteMode::AdjustmentIn &&
mode != WHSWorkExecuteMode::ReportAsFinished &&
...
...
...
//memre 22.12.2015
mode != WHSWorkExecuteMode::PurchaseOrderLineReceivingWithVendor &&
//memre
mode != WHSWorkExecuteMode::PurchaseOrderItemReceivingAndLocate &&
...
...
Bildiğim kadarıyla tüm temel noktalar bunlar. Daha fazla ayrıntı için benim de faydalandığım blog ve WMS dökümanından faydalanabilirsiniz.
Klavuzda geliştirme hakkında bir bilgi yok. Ben bu konuda bulduğum bir blogdan faydalandım. Kendim uğraşsam bulamayacağımı sandığım püf noktalarını da hiçbir çaba sarfetmeden bu blogdan öğrenmiş oldum. :)
El terminali geliştirme yöntemini anlatırken WMS dökümanında anlatılan konuları bildiğinizi farzedeceğim.
El terminali geliştirmesi tamamen X++ classlar üzerinden çalışıyor. Yaptığınız her yeni menu item için bir class oluyor. Tüm menu item classları WMSWorkExecuteDisplay ile başlıyor.
Kendi menu itemimizi geliştirdiğimizi farzedelim. Eğer kendi menu itemimizi geliştirmeyeceksek bu adımı atlayabiliriz:
Yeni bir work ve/veya indirect menu item ekleyeceğiniz zaman WHSWorkCreationProcess enumuna bunu yeni bir eleman olarak eklemelisiniz. Eğer eklediğiniz menu item bir work ise ayrıca WHSWorkExecuteMode enum içine de eklemeniz gerekiyor. Okuduğum blogda yazdığına göre WHSWorkExecuteMode içine eklediğiniz elemanın adı ve label içeriği WHSWorkCreationProcess içine eklediğiniz ile birebir aynı olmalıymış, ben bunu hiç test etmedim, aynen söylenene uydum. Bizim elemanın adı Test olsun.
Bizim sınıfın adının WMSWorkExecuteDisplayTest olduğunu farzedelim. Sınıfımız WHSWorkExecuteDisplay sınıfından türeyecek.
Yukarıda anlattığımız enumlara eklenen eleman sayesinde kullanıcıya menu item tanımlama ekranında (Mobile device menu items ->Genel->Work creation process) yeni bir menu item daha görülebilecek. Ancak onun çağrılabilmesini sağlamak için yapılması gereken birşey daha var; WHSWorkExecuteDisplay sınıfının construct metodundaki switch/case bloğuna aşağıdaki kod parçasını eklemek:
case WHSWorkExecuteMode::MyTest : return WHSWorkExecuteDisplayTest::construct();
El terminali geliştirmesindeki tüm menu itemler kendi sınıfları içindeki displayForm metodu vasıtasıyla çalışıyor. Ben mevcut sınıflardan birini alıp kopyaladım ve onun üzerinde yaptığım değişikliklerle işimi gördüm. displayForm metodu aşamalar şeklinde çalışıyor. Bunu step isimli değişkenle takip ediyor. birinci aşama sıfır. Benim kopyaladığım sınıfta son aşama 2 olan kayıt aşamasıydı. Aşamaları orijinal sınıflarda da yapıldığı gibi displayForm metodunda bir switch/case ile takip edebilirsiniz.
Web formumuza yeni bir kontrol eklemek için buildControl metodunu kullanıyoruz:
ret += [this.buildControl(#RFText, #vendor, "@SYS14048", 1, pass.lookup(#vendor), extendedTypeNum(VendAccount), '', 0,false)];
Yukarıdaki kontroldeki #vendor makrosu WHSRF makrosunda yoksa bizim bunu ayrıca eklememiz gerekiyor. Yine blogdan öğrendiğim üzere bu metodun parametreleri şöyle (ordan copy/paste yapıp türkçeye çevirdim sadece):
Paremetre | Data tipi | Açıklama |
_controlType | str | Kontrolün türü. Bu türler WHSRF makrosunda eklenen türlerden biri olmak zorunda: #define.RFButton('button') #define.RFLabel('label') #define.RFText('text') #define.RFPassword('password') #define.RFListbox('listbox') #define.RFCombobox('combobox') #define.RFError('error') |
_name | str | Kontrolün ismi. Kontrolde saklanan dataya ulaşmak için bu ismi kullanacağız. |
_label | str | UI'de gözükecek text içeriği. |
_newLine | int | 1 ise kontrol yeni bir satırda olacak, 0 ise aynı satırda. |
_data | str | Kontrolde gösterilecek data. |
_inputType | ExtendedTypeId | Kontrolün data türü. Doğrulama için bu önemli. Doğrulama gerekmiyorsa #WHSRFUndefinedDataType makrosu kullanılabilir. |
_error | str | Doğrulama gerçekleşmediğinde çıkacak mesaj. |
_defaultButton | int | 1 ise buton kontrolü varsayılan kontrol demektir, Genellikle "Tamam" butonu için kullanılır. |
_enabled | boolean | true olduğunda kontrol enabled olur, false olduğunda disabled, default enabled. |
_selected | int | 1 olduğunda aktif kontrol olur. |
_color | WHSRFColorText | Kontrolün rengi. WHSRFColorText enumda tanımlı birkaç renk var. |
Kontrolde kullandığımız datanın map edilip edilmediğini öğrenmek için exists, edilmişse de değerini öğrenmek için lookup metodlarını kullanıyoruz. Genelde aşağıdaki şekilde kullanılıyor:
if (pass.exists(#vendor) && pass.lookup(#vendor) != '")
Data değerini eklemek/değiştirmek için insert metodunu kullanıyoruz:
pass.insert(#vendor,purchTable.OrderAccount);
Bu arada Mobile device menu items formunda diğer menu itemlerinde gözüken ancak sizinkinde gözükmeyen seçenekleri görmek istiyorsanız bunun için (daire içinde işaretlediklerim)
WHSRFMenuItem formunun togglefields metodunda ufak bir değişiklik gerekiyor:
if (whsrfMenuItemTable.WorkCreationProcess == WHSWorkCreationProcess::PurchaseOrderItemReceiving ||
whsrfMenuItemTable.WorkCreationProcess ==
...
...
//memre 22.12.2015
whsrfMenuItemTable.WorkCreationProcess == WHSWorkCreationProcess::PurchaseOrderLineReceivingWithVendor)
//memre
...
...
Aynı zamanda WHSRFControlData sınıfının processControl metodunda ekstra güncellemeler yapmanız gerekebilir. Benim yaptığım bir geliştirmede orijinalinden kopyaladığım sınıfta orijinalinde LP (License Plate) oluşurken benimkinde oluşmuyordu. Sebebiyse enum ile yapılan LP kontrolüydü. Benim için aşağıdaki güncelleme iş gördü:
case #LicensePlateId:
...
...
else if (mode != WHSWorkExecuteMode::AdjustmentIn &&
mode != WHSWorkExecuteMode::ReportAsFinished &&
...
...
...
//memre 22.12.2015
mode != WHSWorkExecuteMode::PurchaseOrderLineReceivingWithVendor &&
//memre
mode != WHSWorkExecuteMode::PurchaseOrderItemReceivingAndLocate &&
...
...
Bildiğim kadarıyla tüm temel noktalar bunlar. Daha fazla ayrıntı için benim de faydalandığım blog ve WMS dökümanından faydalanabilirsiniz.
Etiketler:
2012,
ax,
AXAPTA,
development,
el,
el terminali,
geliştirme,
new,
terminal,
wms,
yeni
1 Aralık 2015 Salı
AX 2012 - Try - catch
Try/catch hakkında güzel bir uyarı yazısı var. Aşağıdaki kod oradan alıntı:
void post(int amount)
{
#OCCRetryCount
MyPostings debit;
MyPostings credit;
System.Exception ex;
try
{
ttsBegin;
debit = MyPostings::find('debit', true);
debit.Amount += amount;
debit.update();
credit = MyPostings::find('credit', true);
credit.Amount -= amount;
credit.update();
ttsCommit;
}
catch (Exception::UpdateConflict)
{
if (appl.ttsLevel() != 0)
{
throw Exception::UpdateConflict;
}
if (xSession::currentRetryCount() >= #RetryNum)
{
throw Exception::UpdateConflictNotRecovered;
}
retry;
}
catch (Exception::DuplicateKeyException)
{
if (appl.ttsLevel() != 0)
{
throw Exception::DuplicateKeyException;
}
if (xSession::currentRetryCount() >= #RetryNum)
{
throw Exception::DuplicateKeyExceptionNotRecovered;
}
retry;
}
catch (Exception::Deadlock)
{
if (xSession::currentRetryCount() >= #RetryNum)
{
throw Exception::Deadlock;
}
retry;
}
catch(Exception::CLRError)
{
ex = ClrInterop::getLastException();
if (ex != null)
{
ex = ex.get_InnerException();
if (ex != null)
{
error(ex.ToString());
}
else
error(AifUtil::getClrErrorMessage());
}
else
error(AifUtil::getClrErrorMessage());
{
warning(infolog.text());
if (appl.ttsLevel() != 0)
{
throw error("Something happened, that the logic was not designed to handle – please log a bug.");
}
error("Something bad happened - try again later");
}
}
void post(int amount)
{
#OCCRetryCount
MyPostings debit;
MyPostings credit;
System.Exception ex;
try
{
ttsBegin;
debit = MyPostings::find('debit', true);
debit.Amount += amount;
debit.update();
credit = MyPostings::find('credit', true);
credit.Amount -= amount;
credit.update();
ttsCommit;
}
catch (Exception::UpdateConflict)
{
if (appl.ttsLevel() != 0)
{
throw Exception::UpdateConflict;
}
if (xSession::currentRetryCount() >= #RetryNum)
{
throw Exception::UpdateConflictNotRecovered;
}
retry;
}
catch (Exception::DuplicateKeyException)
{
if (appl.ttsLevel() != 0)
{
throw Exception::DuplicateKeyException;
}
if (xSession::currentRetryCount() >= #RetryNum)
{
throw Exception::DuplicateKeyExceptionNotRecovered;
}
retry;
}
catch (Exception::Deadlock)
{
if (xSession::currentRetryCount() >= #RetryNum)
{
throw Exception::Deadlock;
}
retry;
}
catch(Exception::CLRError)
{
ex = ClrInterop::getLastException();
if (ex != null)
{
ex = ex.get_InnerException();
if (ex != null)
{
error(ex.ToString());
}
else
error(AifUtil::getClrErrorMessage());
}
else
error(AifUtil::getClrErrorMessage());
}
catch {
warning(infolog.text());
if (appl.ttsLevel() != 0)
{
throw error("Something happened, that the logic was not designed to handle – please log a bug.");
}
error("Something bad happened - try again later");
}
}
AX 2012 - Müşteri ve satıcı hesabı ekleme/güncelleme
Müşteri hesabı:
CustTable custTable;
DirParty dirParty;
DirPartyPostalAddressView dirPartyPostalAddressView;
DirPartyContactInfoView dirPartyContactInfo;
CustGroup custGroup;
DirPartyTable partyTable;
DirPartyLocation dirLocation;
LogisticsPostalAddress address;
LogisticsLocation logisticsLocation;
;
select firstOnly forUpdate custTable
where custTable.AccountNum == custAccount;
//-------------------- custtable --------------------------
if (custTable.RecId == 0)
{
custTable.initValue();
custTable.AccountNum = custAccount;
custTable.CustGroup = custGroupId;
custTable.VATNum = vatNum;
custTable.IdentificationNumber = identificationNumber;
custTable.TaxOfficeName_TR = taxOfficeName_TR;
custTable.Blocked = custBlocked;
custTable.insert(DirPartyType::Organization, custName);
}
else
{
custTable.CustGroup = custGroupId;
custTable.VATNum = vatNum;
custTable.TaxOfficeName_TR = taxOfficeName_TR;
custTable.IdentificationNumber = identificationNumber;
custTable.Blocked = custBlocked;
custTable.update();
update_recordSet partyTable setting name = custName, NameAlias = nameAlias
where partyTable.RecId == custTable.Party;
}
//-------------------- adres -----------------------------
dirParty = DirParty::constructFromCommon(custTable);
select firstonly dirPartyPostalAddressView
where dirPartyPostalAddressView.Party == custTable.Party &&
dirPartyPostalAddressView.LocationName == "Adres";
dirPartyPostalAddressView.LocationName = "Adres";
dirPartyPostalAddressView.City = city;
dirPartyPostalAddressView.State = state;
dirPartyPostalAddressView.Street = street;
dirPartyPostalAddressView.IsPrimary = NoYes::Yes;
dirPartyPostalAddressView.CountryRegionId = countryRegionId;
dirParty.createOrUpdatePostalAddress(dirPartyPostalAddressView);
if (phone)
{
dirParty = DirParty::constructFromCommon(custTable);
select dirPartyContactInfo
where firstonly dirPartyContactInfo.Party == custTable.Party &&
dirPartyContactInfo.LocationName == "Telefon";
dirPartyContactInfo.LocationName ="Telefon";
dirPartyContactInfo.Locator = phone;
dirPartyContactInfo.IsPrimary = NoYes::Yes;
dirPartyContactInfo.Type = LogisticsElectronicAddressMethodType::Phone;
dirParty.createOrUpdateContactInfo(dirPartyContactInfo);
}
if (email)
{
select firstonly dirPartyContactInfo
where dirPartyContactInfo.Party == custTable.Party &&
dirPartyContactInfo.LocationName == "E-mail";
dirPartyContactInfo.LocationName ="E-mail";
dirPartyContactInfo.Locator = email;
dirPartyContactInfo.IsPrimary = NoYes::Yes;
dirPartyContactInfo.Type = LogisticsElectronicAddressMethodType::Email;
dirParty.createOrUpdateContactInfo(dirPartyContactInfo);
}
Satıcı hesabı eklemenin müşteri hesabı eklemekten tek farkı dirParty kaydının ayrıca oluşturulması . Eğer hesap organizasyon yerine bir kişi ise DirOrganization tablosu yerine DirPersonName tablosu kullanılıyor:
VendTable vendTable;
DirParty dirParty;
DirPartyPostalAddressView dirPartyPostalAddressView;
DirPartyContactInfoView dirPartyContactInfo;
VendGroup vendGroup;
DirPartyTable partyTable;
DirPartyLocation dirLocation;
LogisticsPostalAddress address;
LogisticsLocation logisticsLocation;
DirOrganization organization;
;
select firstOnly forUpdate vendTable
where vendTable.AccountNum == vendAccount;
//-------------------- vendTable --------------------------
if (vendTable.RecId == 0)
{
organization.Name = vendName;
organization.NameAlias = nameAlias;
organization.LanguageId = CompanyInfo::languageId();
organization.insert();
vendTable.initValue();
vendTable.party = organization.recid;
vendTable.AccountNum = vendAccount;
vendTable.vendGroup = vendGroupId;
vendTable.VATNum = vatNum;
vendTable.Blocked = VendBlocked;
vendTable.TaxOfficeName_TR = taxOfficeName_TR;
vendTable.insert();
}
else
{
vendTable.vendGroup = vendGroupId;
vendTable.VATNum = vatNum;
vendTable.Blocked = VendBlocked;
vendTable.update();
update_recordSet organization setting name = vendName, NameAlias = nameAlias
where organization.RecId == vendTable.Party;
}
CustTable custTable;
DirParty dirParty;
DirPartyPostalAddressView dirPartyPostalAddressView;
DirPartyContactInfoView dirPartyContactInfo;
CustGroup custGroup;
DirPartyTable partyTable;
DirPartyLocation dirLocation;
LogisticsPostalAddress address;
LogisticsLocation logisticsLocation;
;
select firstOnly forUpdate custTable
where custTable.AccountNum == custAccount;
//-------------------- custtable --------------------------
if (custTable.RecId == 0)
{
custTable.initValue();
custTable.AccountNum = custAccount;
custTable.CustGroup = custGroupId;
custTable.VATNum = vatNum;
custTable.IdentificationNumber = identificationNumber;
custTable.TaxOfficeName_TR = taxOfficeName_TR;
custTable.Blocked = custBlocked;
custTable.insert(DirPartyType::Organization, custName);
}
else
{
custTable.CustGroup = custGroupId;
custTable.VATNum = vatNum;
custTable.TaxOfficeName_TR = taxOfficeName_TR;
custTable.IdentificationNumber = identificationNumber;
custTable.Blocked = custBlocked;
custTable.update();
update_recordSet partyTable setting name = custName, NameAlias = nameAlias
where partyTable.RecId == custTable.Party;
}
//-------------------- adres -----------------------------
dirParty = DirParty::constructFromCommon(custTable);
select firstonly dirPartyPostalAddressView
where dirPartyPostalAddressView.Party == custTable.Party &&
dirPartyPostalAddressView.LocationName == "Adres";
dirPartyPostalAddressView.LocationName = "Adres";
dirPartyPostalAddressView.City = city;
dirPartyPostalAddressView.State = state;
dirPartyPostalAddressView.Street = street;
dirPartyPostalAddressView.IsPrimary = NoYes::Yes;
dirPartyPostalAddressView.CountryRegionId = countryRegionId;
dirParty.createOrUpdatePostalAddress(dirPartyPostalAddressView);
if (phone)
{
dirParty = DirParty::constructFromCommon(custTable);
select dirPartyContactInfo
where firstonly dirPartyContactInfo.Party == custTable.Party &&
dirPartyContactInfo.LocationName == "Telefon";
dirPartyContactInfo.LocationName ="Telefon";
dirPartyContactInfo.Locator = phone;
dirPartyContactInfo.IsPrimary = NoYes::Yes;
dirPartyContactInfo.Type = LogisticsElectronicAddressMethodType::Phone;
dirParty.createOrUpdateContactInfo(dirPartyContactInfo);
}
if (email)
{
select firstonly dirPartyContactInfo
where dirPartyContactInfo.Party == custTable.Party &&
dirPartyContactInfo.LocationName == "E-mail";
dirPartyContactInfo.LocationName ="E-mail";
dirPartyContactInfo.Locator = email;
dirPartyContactInfo.IsPrimary = NoYes::Yes;
dirPartyContactInfo.Type = LogisticsElectronicAddressMethodType::Email;
dirParty.createOrUpdateContactInfo(dirPartyContactInfo);
}
Satıcı hesabı eklemenin müşteri hesabı eklemekten tek farkı dirParty kaydının ayrıca oluşturulması . Eğer hesap organizasyon yerine bir kişi ise DirOrganization tablosu yerine DirPersonName tablosu kullanılıyor:
VendTable vendTable;
DirParty dirParty;
DirPartyPostalAddressView dirPartyPostalAddressView;
DirPartyContactInfoView dirPartyContactInfo;
VendGroup vendGroup;
DirPartyTable partyTable;
DirPartyLocation dirLocation;
LogisticsPostalAddress address;
LogisticsLocation logisticsLocation;
DirOrganization organization;
;
select firstOnly forUpdate vendTable
where vendTable.AccountNum == vendAccount;
//-------------------- vendTable --------------------------
if (vendTable.RecId == 0)
{
organization.Name = vendName;
organization.NameAlias = nameAlias;
organization.LanguageId = CompanyInfo::languageId();
organization.insert();
vendTable.initValue();
vendTable.party = organization.recid;
vendTable.AccountNum = vendAccount;
vendTable.vendGroup = vendGroupId;
vendTable.VATNum = vatNum;
vendTable.Blocked = VendBlocked;
vendTable.TaxOfficeName_TR = taxOfficeName_TR;
vendTable.insert();
}
else
{
vendTable.vendGroup = vendGroupId;
vendTable.VATNum = vatNum;
vendTable.Blocked = VendBlocked;
vendTable.update();
update_recordSet organization setting name = vendName, NameAlias = nameAlias
where organization.RecId == vendTable.Party;
}
30 Kasım 2015 Pazartesi
AX 2012 - Ürün ekleme/güncelleme
//http://daxtechies.blogspot.com.tr/2013/12/ax2012-r2-creating-product-or-product.html
if ( InventTable::find(itemId).ItemId != "" )
this.updateProduct();
else
this.newProduct();
itemRecId = EcoResProduct::findByDisplayProductNumber(itemId).RecId;
this.updateInventTable();
private void newProduct(EcoResProductSubtype _subType = EcoResProductSubtype::Product)
{
EcoResProductService erProdSvc;
EcoResEcoResProduct ecoResProd;
EcoResEcoResProduct_Product_Master prodMaster;
EcoResEcoResProduct_Translation translation;
EcoResEcoResProduct_Identifier identifier;
EcoResEcoResProduct_ProductDimGroup prodDimGroup;
EcoResEcoResProduct_Product_Distinct distMaster;
EcoResEcoResProduct_StorageDimGroup storDimGroup;
EcoResEcoResProduct_TrackingDimGroup tracDimGroup;
InventTable inventTable;
erProdSvc = EcoResProductService::construct();
ecoResProd = new EcoResEcoResProduct();
if (_subType == EcoResProductSubtype::ProductMaster) //varyantlı ürün
{
prodMaster = new EcoResEcoResProduct_Product_Master();
prodMaster.parmDisplayProductNumber(itemId);
prodMaster.parmProductType(EcoResProductType::Item);
prodMaster.parmSearchName(nameAlias);
prodMaster.parmVariantConfigurationTechnology(EcoResVariantConfigurationTechnologyType::PredefinedVariants);
translation = prodMaster.createTranslation().addNew();
identifier = prodMaster.createIdentifier().addNew();
prodDimGroup = prodMaster.createProductDimGroup().addNew();
prodDimGroup.parmProduct(itemId);
prodDimGroup.parmProductDimensionGroup(dimGroup);
storDimGroup = prodMaster.createStorageDimGroup().addNew();
tracDimGroup = prodMaster.createTrackingDimGroup().addNew();
}
if (_subType == EcoResProductSubtype::Product) //varyantsız ürün
{
distMaster = new EcoResEcoResProduct_Product_Distinct();
distMaster.parmDisplayProductNumber(itemId);
distMaster.parmProductType(EcoResProductType::Item);
distMaster.parmSearchName(nameAlias);
translation = distMaster.createTranslation().addNew();
identifier = distMaster.createIdentifier().addNew();
storDimGroup = distMaster.createStorageDimGroup().addNew();
tracDimGroup = distMaster.createTrackingDimGroup().addNew();
}
translation.parmDescription(itemName);
translation.parmLanguageId(SystemParameters::getSystemLanguageId());
translation.parmName(itemName);
storDimGroup.parmProduct(itemId);
storDimGroup.parmStorageDimensionGroup(storeGroup);
tracDimGroup.parmProduct(itemId);
tracDimGroup.parmTrackingDimensionGroup(trackingGroup);
identifier.parmProductNumber(itemId);
if (_subType == EcoResProductSubtype::ProductMaster) //varyantlı ürün
ecoResProd.createProduct().add(prodMaster);
if (_subType == EcoResProductSubtype::Product) //varyantsız ürün
ecoResProd.createProduct().add(distMaster);
erProdSvc.create(ecoResProd);
EcoResProductReleaseManagerBase::releaseProduct(EcoResProduct::findByProductNumber(itemId).RecId,CompanyInfo::find().RecId);
}
private void updateProduct()
{
InventTableModule inventModule;
EcoResProductTranslation translation;
update_recordSet inventModule setting unitId = unitId
where inventModule.ItemId == itemId;
update_recordSet translation
setting Description = itemName,
Name = itemName
where translation.Product == itemRecId &&
translation.LanguageId == SystemParameters::getSystemLanguageId();
}
private void updateInventTable()
{
InventTable inventTable;
InventModelGroupItem modelGroup;
update_recordSet inventTable
setting NetWeight = netWeight,
TaraWeight = taraWeight,
GrossDepth = depth,
GrossWidth = width,
GrossHeight = height,
UnitVolume = volume
where
inventTable.Product == itemRecId;
if (inventModelGroupId == "")
delete_from modelGroup
where modelGroup.ItemId == itemId && modelGroup.ItemDataAreaId == curext() &&
modelGroup.ModelGroupDataAreaId == curext();
else
{
select firstOnly forUpdate modelGroup
where modelGroup.ItemId == itemId && modelGroup.ItemDataAreaId == curext() &&
modelGroup.ModelGroupDataAreaId == curext();
modelGroup.ItemId = itemId;
modelGroup.ItemDataAreaId = curext();
modelGroup.ModelGroupDataAreaId = curext();
modelGroup.ModelGroupId = inventModelGroupId;
if (modelGroup.RecId == 0)
modelGroup.insert();
else
modelGroup.update();
}
}
if ( InventTable::find(itemId).ItemId != "" )
this.updateProduct();
else
this.newProduct();
itemRecId = EcoResProduct::findByDisplayProductNumber(itemId).RecId;
this.updateInventTable();
private void newProduct(EcoResProductSubtype _subType = EcoResProductSubtype::Product)
{
EcoResProductService erProdSvc;
EcoResEcoResProduct ecoResProd;
EcoResEcoResProduct_Product_Master prodMaster;
EcoResEcoResProduct_Translation translation;
EcoResEcoResProduct_Identifier identifier;
EcoResEcoResProduct_ProductDimGroup prodDimGroup;
EcoResEcoResProduct_Product_Distinct distMaster;
EcoResEcoResProduct_StorageDimGroup storDimGroup;
EcoResEcoResProduct_TrackingDimGroup tracDimGroup;
InventTable inventTable;
erProdSvc = EcoResProductService::construct();
ecoResProd = new EcoResEcoResProduct();
if (_subType == EcoResProductSubtype::ProductMaster) //varyantlı ürün
{
prodMaster = new EcoResEcoResProduct_Product_Master();
prodMaster.parmDisplayProductNumber(itemId);
prodMaster.parmProductType(EcoResProductType::Item);
prodMaster.parmSearchName(nameAlias);
prodMaster.parmVariantConfigurationTechnology(EcoResVariantConfigurationTechnologyType::PredefinedVariants);
translation = prodMaster.createTranslation().addNew();
identifier = prodMaster.createIdentifier().addNew();
prodDimGroup = prodMaster.createProductDimGroup().addNew();
prodDimGroup.parmProduct(itemId);
prodDimGroup.parmProductDimensionGroup(dimGroup);
storDimGroup = prodMaster.createStorageDimGroup().addNew();
tracDimGroup = prodMaster.createTrackingDimGroup().addNew();
}
if (_subType == EcoResProductSubtype::Product) //varyantsız ürün
{
distMaster = new EcoResEcoResProduct_Product_Distinct();
distMaster.parmDisplayProductNumber(itemId);
distMaster.parmProductType(EcoResProductType::Item);
distMaster.parmSearchName(nameAlias);
translation = distMaster.createTranslation().addNew();
identifier = distMaster.createIdentifier().addNew();
storDimGroup = distMaster.createStorageDimGroup().addNew();
tracDimGroup = distMaster.createTrackingDimGroup().addNew();
}
translation.parmDescription(itemName);
translation.parmLanguageId(SystemParameters::getSystemLanguageId());
translation.parmName(itemName);
storDimGroup.parmProduct(itemId);
storDimGroup.parmStorageDimensionGroup(storeGroup);
tracDimGroup.parmProduct(itemId);
tracDimGroup.parmTrackingDimensionGroup(trackingGroup);
identifier.parmProductNumber(itemId);
if (_subType == EcoResProductSubtype::ProductMaster) //varyantlı ürün
ecoResProd.createProduct().add(prodMaster);
if (_subType == EcoResProductSubtype::Product) //varyantsız ürün
ecoResProd.createProduct().add(distMaster);
erProdSvc.create(ecoResProd);
EcoResProductReleaseManagerBase::releaseProduct(EcoResProduct::findByProductNumber(itemId).RecId,CompanyInfo::find().RecId);
}
private void updateProduct()
{
InventTableModule inventModule;
EcoResProductTranslation translation;
update_recordSet inventModule setting unitId = unitId
where inventModule.ItemId == itemId;
update_recordSet translation
setting Description = itemName,
Name = itemName
where translation.Product == itemRecId &&
translation.LanguageId == SystemParameters::getSystemLanguageId();
}
private void updateInventTable()
{
InventTable inventTable;
InventModelGroupItem modelGroup;
update_recordSet inventTable
setting NetWeight = netWeight,
TaraWeight = taraWeight,
GrossDepth = depth,
GrossWidth = width,
GrossHeight = height,
UnitVolume = volume
where
inventTable.Product == itemRecId;
if (inventModelGroupId == "")
delete_from modelGroup
where modelGroup.ItemId == itemId && modelGroup.ItemDataAreaId == curext() &&
modelGroup.ModelGroupDataAreaId == curext();
else
{
select firstOnly forUpdate modelGroup
where modelGroup.ItemId == itemId && modelGroup.ItemDataAreaId == curext() &&
modelGroup.ModelGroupDataAreaId == curext();
modelGroup.ItemId = itemId;
modelGroup.ItemDataAreaId = curext();
modelGroup.ModelGroupDataAreaId = curext();
modelGroup.ModelGroupId = inventModelGroupId;
if (modelGroup.RecId == 0)
modelGroup.insert();
else
modelGroup.update();
}
}
16 Kasım 2015 Pazartesi
AXAPTA - Kod içinde şirket değiştirmek
Kod içinde şirket değiştirmek kolay. Ancak iki ufak noktaya dikkat etmek gerekiyor; select/SQL kullanılıyorsa select/SQL için kullanılan yerel tablo adını nulllamak gerekiyor. Query kullanılıyorsa da queryin loop içinde her seferinde yeniden oluşturulması gerekiyor. Query.reset() bu konuda bir işe yaramıyor:
Query:
changeCompany(dataArea.Id)
{
qRun = new QueryRun(q);
while (qRun.next())
{
custTable = qRun.get(tablenum(CustTable));
...
}
}
Select/SQL:
changeCompany(dataArea.Id)
{
custTable = null;
subSegmentGroup = null;
while select AccountNum from custTable
...
Query:
changeCompany(dataArea.Id)
{
qRun = new QueryRun(q);
while (qRun.next())
{
custTable = qRun.get(tablenum(CustTable));
...
}
}
Select/SQL:
changeCompany(dataArea.Id)
{
custTable = null;
subSegmentGroup = null;
while select AccountNum from custTable
...
13 Kasım 2015 Cuma
AXAPTA - Kodla security check kontrolü
Bazen kodla security check yapmak gerekir (Display metod vb.. durumlarda):
SecurityKeySet securityKeys = new SecurityKeySet();
;
securityKeys.loadUserRights(curuserid());
if (securityKeys.access(securitykeynum("KRC_CrossCompany")) == AccessType::NoAccess)
chkCrsCompany.value(NoYes::No);
SecurityKeySet securityKeys = new SecurityKeySet();
;
securityKeys.loadUserRights(curuserid());
if (securityKeys.access(securitykeynum("KRC_CrossCompany")) == AccessType::NoAccess)
chkCrsCompany.value(NoYes::No);
12 Kasım 2015 Perşembe
AXAPTA - SysInfoAction sınıfıyla info fonksiyonuna ekstra görev getirme
Bu sınıf ile bir formu çağırmanın iki yolu var:
info(strfmt("Satış siparişi oluşturuldu: %1",salesTable.SalesId),"",
SysInfoAction_TableField::newBuffer(salesTable));
Yukarıdaki yöntemin aşağıdakinden farklı bir record datası göndermemesi:
SysInfoAction_FormRun infoAction = SysInfoAction_FormRun::newFormName(formStr(SalesTable));
;
infoAction.parmCallerBuffer(salestable);
info(strfmt("Satış siparişi oluşturuldu: %1",salesTable.SalesId),"",
infoaction);
info(strfmt("Satış siparişi oluşturuldu: %1",salesTable.SalesId),"",
SysInfoAction_TableField::newBuffer(salesTable));
Yukarıdaki yöntemin aşağıdakinden farklı bir record datası göndermemesi:
SysInfoAction_FormRun infoAction = SysInfoAction_FormRun::newFormName(formStr(SalesTable));
;
infoAction.parmCallerBuffer(salestable);
info(strfmt("Satış siparişi oluşturuldu: %1",salesTable.SalesId),"",
infoaction);
16 Ekim 2015 Cuma
AXAPTA - Formlarda pack-unpack
ClassDeclaration metodu:
Container packedQuery;
SysQueryRun qRun;
str dummy;
#DEFINE.CurrentVersion(1)
#LOCALMACRO.CurrentList
dummy,
packedQuery
#ENDMACRO
Diğer metodlar:
container pack()
{
;
dummy = txtDummy.valuestr();
return [#CurrentVersion,#CurrentList];
}
public boolean unpack(container _packedClass)
{
int version = conPeek(_packedClass,1);
switch (version)
{
case #CurrentVersion:
[version,#CurrentList] = _packedClass;
break;
default:
return false;
}
return true;
}
public void init()
{
;
xSysLastValue::getLast(this);
super();
txtDummy(dummy);
element.initQuery();
}
public void close()
{
super();
xSysLastValue::saveLast(this);
}
void initParmDefault()
{
}
private IdentifierName lastValueDesignName()
{
return '';
}
private IdentifierName lastValueElementName()
{
return this.name();
}
private UtilElementType lastValueType()
{
return UtilElementType::Form;
}
private UserId lastValueUserId()
{
return curuserid();
}
public dataAreaId lastValueDataAreaId()
{
return curExt();
}
Bu metod zorunlu değil, ancak query kullanacaksanız buna benzer birşey yazabilirsiniz:
void initQuery()
{
Query q;
QueryBuildDataSource qbds;
QueryBuildDataSource qbds2;
QueryBuildRange qRange;
;
if (packedQuery)
qRun = new SysQueryRun(packedQuery);
else
{
q = new query();
qbds = q.addDataSource(tablenum(EmplTable));
qRun = new SysQueryRun(q);
}
qRun.promptLoadLastUsedQuery(false);
}
Bu metod da query'nin select butonu için, yani bu da zorunlu değil:
void clicked()
{
;
super();
if (qRun.prompt())
packedQuery = qRun.pack();
}
Container packedQuery;
SysQueryRun qRun;
str dummy;
#DEFINE.CurrentVersion(1)
#LOCALMACRO.CurrentList
dummy,
packedQuery
#ENDMACRO
Diğer metodlar:
container pack()
{
;
dummy = txtDummy.valuestr();
return [#CurrentVersion,#CurrentList];
}
public boolean unpack(container _packedClass)
{
int version = conPeek(_packedClass,1);
switch (version)
{
case #CurrentVersion:
[version,#CurrentList] = _packedClass;
break;
default:
return false;
}
return true;
}
public void init()
{
;
xSysLastValue::getLast(this);
super();
txtDummy(dummy);
element.initQuery();
}
public void close()
{
super();
xSysLastValue::saveLast(this);
}
void initParmDefault()
{
}
private IdentifierName lastValueDesignName()
{
return '';
}
private IdentifierName lastValueElementName()
{
return this.name();
}
private UtilElementType lastValueType()
{
return UtilElementType::Form;
}
private UserId lastValueUserId()
{
return curuserid();
}
public dataAreaId lastValueDataAreaId()
{
return curExt();
}
Bu metod zorunlu değil, ancak query kullanacaksanız buna benzer birşey yazabilirsiniz:
void initQuery()
{
Query q;
QueryBuildDataSource qbds;
QueryBuildDataSource qbds2;
QueryBuildRange qRange;
;
if (packedQuery)
qRun = new SysQueryRun(packedQuery);
else
{
q = new query();
qbds = q.addDataSource(tablenum(EmplTable));
qRun = new SysQueryRun(q);
}
qRun.promptLoadLastUsedQuery(false);
}
Bu metod da query'nin select butonu için, yani bu da zorunlu değil:
void clicked()
{
;
super();
if (qRun.prompt())
packedQuery = qRun.pack();
}
12 Ekim 2015 Pazartesi
AXAPTA - Form kontrolüne sağ mouse popup menübar eklemek
Bunu kontrolün showContextMenu metodunu düzenleyerek yapabilirsiniz:
public int showContextMenu(int _menuHandle)
{
int ret;
int bar1,bar2;
PopupMenu pMenu = PopupMenu::create(_menuHandle,element.hWnd());
;
bar1 = pMenu.insertItem("Seçenek 1");
bar2 = pMenu.insertItem("Seçenek 2");
ret = pMenu.draw();
switch (ret)
{
case -1 :
break;
case bar1:
...
case bar2:
...
default :
break;
}
return ret;
}
public int showContextMenu(int _menuHandle)
{
int ret;
int bar1,bar2;
PopupMenu pMenu = PopupMenu::create(_menuHandle,element.hWnd());
;
bar1 = pMenu.insertItem("Seçenek 1");
bar2 = pMenu.insertItem("Seçenek 2");
ret = pMenu.draw();
switch (ret)
{
case -1 :
break;
case bar1:
...
case bar2:
...
default :
break;
}
return ret;
}
8 Ekim 2015 Perşembe
Axapta - Dataset gönderme ve alma
Bu kodları Fatih Demirci'nin bir geliştirmesinden aldım.
Dataset gönderme:
System.Data.DataTable dataTable;
System.Data.DataColumnCollection dataTableColumns;
System.Data.DataRowCollection DataRowCollection;
System.Data.DataRow tmpRow;
System.Data.DataSet dataset = new System.Data.DataSet();
System.Data.DataTableCollection dataTableCollection;
dataTable = new System.Data.DataTable();
dataTableColumns = dataTable.get_Columns();
//satırları tanımla
dataTableColumns.Add("ACCOUNTNO", System.Type::GetType("System.String"));
dataTableColumns.Add("ITEMNO", System.Type::GetType("System.String"));
dataTableColumns.Add("TOACCOUNTNUM", System.Type::GetType("System.String"));
dataTableColumns.Add("RETURNREASONIDD", System.Type::GetType("System.String"));
dataTableColumns.Add("QUANTITY", System.Type::GetType("System.Double"));
dataTableColumns.Add("DESCRIPTION", System.Type::GetType("System.String"));
//bir satır al
DataRowCollection = dataTable.get_Rows();
tmpRow = dataTable.NewRow();
//satırı doldur
tmpRow.set_Item("ACCOUNTNO","MU_014600");
tmpRow.set_Item("ITEMNO","200.05.01.0306");
tmpRow.set_Item("TOACCOUNTNUM","MU_014600");
tmpRow.set_Item("RETURNREASONIDD","");
tmpRow.set_Item("QUANTITY",11);
tmpRow.set_Item("DESCRIPTION","");
DataRowCollection.Add(tmpRow);
dataTable.AcceptChanges();
//bu aşamada eğer karşı taraf data table istiyorsa, data table hazır
//eğer dataset istiyorsa bu data tableyi bir datasete ekle
dataTableCollection = dataSet.get_Tables();
dataTableCollection.Add(datatable);
//artık dataset de hazır
Dataset alma:
System.Data.DataTable dataTable;
System.Data.DataTableCollection dataTableCollection;
System.Data.DataColumnCollection dataColumnCollection;
System.Data.DataRowCollection dataRowCollection;
System.Data.DataRow dataRow;
System.Data.DataColumn dataColumn;
System.Data.DataTable returnData;
;
dataTableCollection = dataSet.get_Tables();
totalTable = dataTableCollection.get_Count();
for(i = 0; i < totalTable; i ++)
{
dataTable = dataTableCollection.get_Item(i);
dataColumnCollection = dataTable.get_Columns();
DataRowCollection = dataTable.get_Rows();
totalRow = dataRowCollection.get_Count();
totalCol = dataColumnCollection.get_Count();
for( j = 0; j < totalRow; j ++)
{
dataRow = dataRowCollection.get_Item(j);
custAccount = dataRow.get_Item("ACCOUNTNO");
itemId = dataRow.get_Item("ITEMNO");
toCustAccount = dataRow.get_Item("TOACCOUNTNUM");
strtext = dataRow.get_Item("RETURNREASONIDD");
krc_DefectiveId = str2int64(strtext);
strtext = dataRow.get_Item("QUANTITY");
_b2bdesc = dataRow.get_Item("DESCRIPTION");
...
3 Eylül 2015 Perşembe
Axapta - Query promt "Sorgulama seç - önceden kullanılan sorgu" yu engelleme
Axapta query çalıştırıp range değerleri yüklendiğinde istediğiniz değerlerin gelmediğini görebilirsiniz. Bunun sebebi Sorgulama seç kısmında önceden kullanılan sorgu gelmesi olabilir. Bunu engellemek için QueryRun sınıfı yerine SysQueryRun sınıfını kullanmalısınız. SysQueryRun sınıfı QueryRun sınıfının genişletilmiş halidir.
Aşağıdaki kod "önceden kullanılan sorgu" yerine "kullanılan sorgu"nun gelmesini sağlar:
mySysQueryRun.promptLoadLastUsedQuery(false);
Aşağıdaki kod "önceden kullanılan sorgu" yerine "kullanılan sorgu"nun gelmesini sağlar:
mySysQueryRun.promptLoadLastUsedQuery(false);
Kaydol:
Kayıtlar (Atom)