Bunun için AOT altında örnek bir form (tutorial_LookupMultiSelectGrid) ve hazır bir class var:
public class FormRun extends ObjectRun
{
SysLookupMultiSelectCtrl msCtrl;
}
public void init()
{
...
super();
...
msCtrl = SysLookupMultiSelectCtrl::construct(element, InventLocationIdExc, queryStr(InventLocationSRS));
msCtrl.set(this.InventLocationList());
...
}
Listeyi aşağıdaki gibi alıp yukarıdaki init metod örneğindeki gibi okuyabiliriz.
container InventLocationList()
{
Container Ids,Names;
InventLocation location;
int i;
RecId recId;
for (i=1;i<=conLen(vInventLocationIdExc);i++)
{
recId = conPeek(vInventLocationIdExc,i);
select firstOnly location
where location.RecId == recId;
Ids += location.RecId;
Names += location.InventLocationId;
}
return [Ids,Names];
}
Pack metodda aşağıdaki gibi saklayabiliriz:
container pack()
{
...
vInventLocationIdExc = msCtrl.get();
...
}
Yukarıdaki MsCtrl.Get() metodu RecId değerlerini verirken aşağıdaki de Field değerlerini verir:
container c = msCtrl.getSelectedFieldValues();
Blog Listem
15 Kasım 2017 Çarşamba
14 Kasım 2017 Salı
AX 2012 - Form Grid kontrolüne InventDim ekleme
InventDim tablosunu form data source kısmına ekleyip inventDimId alanının bulunduğu tabloyla (bu örnekte adı SNBProductDemonte) InnerJoin yapın.
Form gride aşağıdaki gibi bir Group kontrol ekleyin:
Forma aşağıdaki kodları ekleyin:
public class FormRun extends ObjectRun
{
InventDimCtrl_Frm_EditDimensions inventDimFormSetup;
}
public void init()
{
super();
...
element.updateDesign(InventDimFormDesignUpdate::Init);
...
}
Object inventDimSetupObject()
{
return inventDimFormSetup;
}
void updateDesign(InventDimFormDesignUpdate mode)
{
InventDimParm inventDimParmVisible;
switch (mode)
{
// Form Init
case InventDimFormDesignUpdate::Init :
if (!inventDimFormSetup)
inventDimFormSetup = InventDimCtrl_Frm_EditDimensions::newFromForm(element);
inventDimFormSetup.parmSkipOnHandLookUp( true);
// Use the methods on InventDimParm
// to set which dimensions to show when form is initialized
// inventdimparmvisible.inventsiteidflag = true;
// inventdimparmvisible.InventLocationIdFlag = true;
inventDimFormSetup.parmDimParmVisibleGrid(inventDimParmVisible);
// Datasource Active
case InventDimFormDesignUpdate::Active :
inventDimFormSetup.formActiveSetup(InventDimGroupSetup::newItemId(SNBProductDemonte.ItemId));
inventDimFormSetup.formSetControls( true);
break;
// Datasource Field change
case InventDimFormDesignUpdate::FieldChange :
inventDimFormSetup.formActiveSetup(InventDimGroupSetup::newItemId(SNBProductDemonte.ItemId));
InventDim.clearNotSelectedDim(inventDimFormSetup.parmDimParmEnabled()); // InventDim is referring to datasource name
inventDimFormSetup.formSetControls( true);
break;
default :
throw error(strFmt ("@SYS54195", funcName()));
}
}
InventDimId alanının olduğu tabloya aşağıdaki kodları ekleyin:
public boolean validateWrite()
{
boolean ret;
SNBProductDemonte.InventDimId = InventDim::findOrCreate(InventDim).InventDimId;
ret = super();
return ret;
}
public int active()
{
int ret;
ret = super();
element.updateDesign(InventDimFormDesignUpdate::Active);
return ret;
}
ItemId alanı modified metoduna aşağıdaki kodu ekleyin:
public void modified()
{
super();
element.updateDesign(InventDimFormDesignUpdate::FieldChange);
InventDim.clearNotSelectedDim(element.inventDimSetupObject().parmDimParmEnabled());
}
Sistemde hazır bulunan InventDimParmFixed isimli Display menu item'i forma ekleyin.
Kaynak:
https://daxbeginners.wordpress.com/2014/08/05/how-to-dynamically-display-inventory-dimension/
Form gride aşağıdaki gibi bir Group kontrol ekleyin:
Forma aşağıdaki kodları ekleyin:
public class FormRun extends ObjectRun
{
InventDimCtrl_Frm_EditDimensions inventDimFormSetup;
}
public void init()
{
super();
...
element.updateDesign(InventDimFormDesignUpdate::Init);
...
}
Object inventDimSetupObject()
{
return inventDimFormSetup;
}
void updateDesign(InventDimFormDesignUpdate mode)
{
InventDimParm inventDimParmVisible;
switch (mode)
{
// Form Init
case InventDimFormDesignUpdate::Init :
if (!inventDimFormSetup)
inventDimFormSetup = InventDimCtrl_Frm_EditDimensions::newFromForm(element);
inventDimFormSetup.parmSkipOnHandLookUp( true);
// Use the methods on InventDimParm
// to set which dimensions to show when form is initialized
// inventdimparmvisible.inventsiteidflag = true;
// inventdimparmvisible.InventLocationIdFlag = true;
inventDimFormSetup.parmDimParmVisibleGrid(inventDimParmVisible);
// Datasource Active
case InventDimFormDesignUpdate::Active :
inventDimFormSetup.formActiveSetup(InventDimGroupSetup::newItemId(SNBProductDemonte.ItemId));
inventDimFormSetup.formSetControls( true);
break;
// Datasource Field change
case InventDimFormDesignUpdate::FieldChange :
inventDimFormSetup.formActiveSetup(InventDimGroupSetup::newItemId(SNBProductDemonte.ItemId));
InventDim.clearNotSelectedDim(inventDimFormSetup.parmDimParmEnabled()); // InventDim is referring to datasource name
inventDimFormSetup.formSetControls( true);
break;
default :
throw error(strFmt ("@SYS54195", funcName()));
}
}
InventDimId alanının olduğu tabloya aşağıdaki kodları ekleyin:
public boolean validateWrite()
{
boolean ret;
SNBProductDemonte.InventDimId = InventDim::findOrCreate(InventDim).InventDimId;
ret = super();
return ret;
}
public int active()
{
int ret;
ret = super();
element.updateDesign(InventDimFormDesignUpdate::Active);
return ret;
}
ItemId alanı modified metoduna aşağıdaki kodu ekleyin:
public void modified()
{
super();
element.updateDesign(InventDimFormDesignUpdate::FieldChange);
InventDim.clearNotSelectedDim(element.inventDimSetupObject().parmDimParmEnabled());
}
Sistemde hazır bulunan InventDimParmFixed isimli Display menu item'i forma ekleyin.
Kaynak:
https://daxbeginners.wordpress.com/2014/08/05/how-to-dynamically-display-inventory-dimension/
Axapta - DateTime Alanlarda İki Gün Arasıda Saniye Kaçırmamak
DateTime alanlarda iki tarih arası rapor alırken ikinci tarihi bir sonraki günün ilk saniyesi olarak alıp <= yerine < kullanmak bir saniye dahi kaçırmamamızı sağlar:
fromDate = DateTimeUtil::newDateTime(FromDateEdit.dateValue(),0,DateTimeUtil::getCompanyTimeZone());
toDate = DateTimeUtil::newDateTime(ToDateEdit.dateValue()+1,0,DateTimeUtil::getCompanyTimeZone());
while select count(RecId) from serviceOrderTable
where serviceOrderTable.createdDateTime >= fromDate
&& serviceOrderTable.createdDateTime < toDate
fromDate = DateTimeUtil::newDateTime(FromDateEdit.dateValue(),0,DateTimeUtil::getCompanyTimeZone());
toDate = DateTimeUtil::newDateTime(ToDateEdit.dateValue()+1,0,DateTimeUtil::getCompanyTimeZone());
while select count(RecId) from serviceOrderTable
where serviceOrderTable.createdDateTime >= fromDate
&& serviceOrderTable.createdDateTime < toDate
10 Kasım 2017 Cuma
AX 2012 - SSRS Raporda Nakli/Devreden Yekün ve Sayfa Toplamı
Maalesef SSRS'te nakli yekün ve sayfa toplamı olması gerekenden çetrefilli. Nakli yekün için bir blogdan (Peter ?), sayfa toplamı için de başka bir blogdan (Annette Theißen) faydalandım.
Nakli yekün ve sayfa toplamı alacağımız alan AccountingCurrencyAmountDebit olsun.
Devreden yekün için tablix kontrolümüze adı dCarry, valuesi aşağıdaki gibi olan bir alan ekliyoruz:
=RunningValue(Fields!AccountingCurrencyAmountDebit.Value,SUM,"LedgerTransListAccountDS")
veya koda göre gruplayacaksak:
=RunningValue(Fields!AccountingCurrencyAmountDebit.Value,SUM,"AccountNum_0")
Nakli yekün için de adı dCarryH olan aşağıdaki gibi bir alan ekliyoruz:
=RunningValue(Fields!AccountingCurrencyAmountDebit.Value,SUM,"AccountNum_0") - Fields!AccountingCurrencyAmountDebit.Value
Her iki alanın da visibility değerini no yapıyoruz. Alanlar gizli de olsa hesaplama yapacak.
Nakli yekün için Page Header kısmına valuesi aşağıdaki gibi olan bir alan ekliyoruz:
=First(ReportItems!dCarryH.Value)
Visibility değerini şarta bağlıyoruz (Böylece ilk sayfada nakli yekün olmayacak):
=Globals!PageNumber=1
Devreden yekün için de Page Footer kısmına da valuesi aşağıdaki gibi olan bir alan ekliyoruz:
=last(ReportItems!dCarry.Value)
Visibility değerini şarta bağlıyoruz (Böylece son sayfada devreden yekün olmayacak):
=Globals!PageNumber=Globals!TotalPages
Sayfa toplamı için iki data method ve variable eklememiz gerekiyor. Data method eklemek için treeview'de Designs altındaki Data Methods nodunda sağ klik - Add Data Method yapıyoruz. Ardından üzerine çift klik yaparak kod ekranını açıyoruz. Eklediğimiz kod aşağıda kırmızı çizili olan parça:
using System;
using System.Collections.Generic;
using System.Security.Permissions;
using System.Data;
using Microsoft.Dynamics.Framework.Reports;
using Microsoft.Dynamics.AX.Application.Reports;
public partial class LedgerTransListAccount
{
static double previousTotal;
static double pageTotal;
static bool NewAccount;
static string lastAccount;
...
[DataMethod(), PermissionSet(SecurityAction.Assert, Name = "FullTrust")]
public static double PageTotal(double total)
{
if (NewAccount)
return total;
else
return total - previousTotal;
}
[DataMethod(), PermissionSet(SecurityAction.Assert, Name = "FullTrust")]
public static double PreviousTotal(double total)
{
previousTotal = total;
return 0;
}
[DataMethod(), PermissionSet(SecurityAction.Assert, Name = "FullTrust")]
public static string Reset()
{
NewAccount = false;
lastAccount = "";
return "";
}
[DataMethod(), PermissionSet(SecurityAction.Assert, Name = "FullTrust")]
public static string FollowAccount(string account)
{
if (lastAccount != "" && lastAccount != account)
NewAccount = true;
lastAccount = account;
return account;
}
}
Page Footera Bir textbox ekliyoruz:
=PreviousTotal(First(ReportItems!dCarryH.Value))
Bu textbox'un visible değerini false yaparsak maalesef hesaplama yapmaz. Display formatı number seçip Show zero as combobox değerini boşluk yapın (None değil!!).
Sayfa toplamını göstermek için bir alan daha ekliyoruz:
=PageTotal(last(ReportItems!dCarry.Value))
Neden yukarıdaki gibi fazladan bir textbox kullandık diyenler için; SSRS malesef expression parametre olarak iki farklı alanı kabul etmiyor.
Sayfa başına bir Textbox ekliyoruz:
=Reset()
Nakli yekün ve sayfa toplamı alacağımız alan AccountingCurrencyAmountDebit olsun.
Devreden yekün için tablix kontrolümüze adı dCarry, valuesi aşağıdaki gibi olan bir alan ekliyoruz:
=RunningValue(Fields!AccountingCurrencyAmountDebit.Value,SUM,"LedgerTransListAccountDS")
veya koda göre gruplayacaksak:
=RunningValue(Fields!AccountingCurrencyAmountDebit.Value,SUM,"AccountNum_0")
Nakli yekün için de adı dCarryH olan aşağıdaki gibi bir alan ekliyoruz:
=RunningValue(Fields!AccountingCurrencyAmountDebit.Value,SUM,"AccountNum_0") - Fields!AccountingCurrencyAmountDebit.Value
Her iki alanın da visibility değerini no yapıyoruz. Alanlar gizli de olsa hesaplama yapacak.
Nakli yekün için Page Header kısmına valuesi aşağıdaki gibi olan bir alan ekliyoruz:
=First(ReportItems!dCarryH.Value)
Visibility değerini şarta bağlıyoruz (Böylece ilk sayfada nakli yekün olmayacak):
=Globals!PageNumber=1
Devreden yekün için de Page Footer kısmına da valuesi aşağıdaki gibi olan bir alan ekliyoruz:
=last(ReportItems!dCarry.Value)
Visibility değerini şarta bağlıyoruz (Böylece son sayfada devreden yekün olmayacak):
=Globals!PageNumber=Globals!TotalPages
Sayfa toplamı için iki data method ve variable eklememiz gerekiyor. Data method eklemek için treeview'de Designs altındaki Data Methods nodunda sağ klik - Add Data Method yapıyoruz. Ardından üzerine çift klik yaparak kod ekranını açıyoruz. Eklediğimiz kod aşağıda kırmızı çizili olan parça:
using System;
using System.Collections.Generic;
using System.Security.Permissions;
using System.Data;
using Microsoft.Dynamics.Framework.Reports;
using Microsoft.Dynamics.AX.Application.Reports;
public partial class LedgerTransListAccount
{
static double previousTotal;
static double pageTotal;
static bool NewAccount;
static string lastAccount;
...
[DataMethod(), PermissionSet(SecurityAction.Assert, Name = "FullTrust")]
public static double PageTotal(double total)
{
if (NewAccount)
return total;
else
return total - previousTotal;
}
[DataMethod(), PermissionSet(SecurityAction.Assert, Name = "FullTrust")]
public static double PreviousTotal(double total)
{
previousTotal = total;
return 0;
}
[DataMethod(), PermissionSet(SecurityAction.Assert, Name = "FullTrust")]
public static string Reset()
{
NewAccount = false;
lastAccount = "";
return "";
}
[DataMethod(), PermissionSet(SecurityAction.Assert, Name = "FullTrust")]
public static string FollowAccount(string account)
{
if (lastAccount != "" && lastAccount != account)
NewAccount = true;
lastAccount = account;
return account;
}
}
Page Footera Bir textbox ekliyoruz:
=PreviousTotal(First(ReportItems!dCarryH.Value))
Bu textbox'un visible değerini false yaparsak maalesef hesaplama yapmaz. Display formatı number seçip Show zero as combobox değerini boşluk yapın (None değil!!).
Sayfa toplamını göstermek için bir alan daha ekliyoruz:
=PageTotal(last(ReportItems!dCarry.Value))
Neden yukarıdaki gibi fazladan bir textbox kullandık diyenler için; SSRS malesef expression parametre olarak iki farklı alanı kabul etmiyor.
Sayfa başına bir Textbox ekliyoruz:
=Reset()
Etiketler:
ax 2012,
AXAPTA,
devreden yekün,
nakli yekün,
rapor,
sayfa,
sayfa toplamı,
ssrs,
toplam
8 Kasım 2017 Çarşamba
AX 2012 - Ürün reçetesi açılımı
Bunun için Christian Silva'nın yazdığı kodları kullandım. Yazar birim çevrimlerini ve renk /bedeni dikkate almamış. Reçetede gram olarak kullanılan bir yarı-mamulün alt reçetede kg'ya çevrilmesi gerekebiliyor. Ben bunları da ekledim:
class SNBBOMExplode
{
SNBBOMExplodeTmp tmpBOM;
SNBBOMExplodeData bomdata;
ItemId itemId;
EcoResItemSizeName inventSizeId;
EcoResItemColorName inventColorId;
InventSiteId inventSiteId;
}
boolean hasChild(ItemId _itemId)
{
BOMVersion bomVersion;
;
//Check if the item is also a BOM item.
select firstonly bomVersion
where bomVersion.ItemId == _itemid
&& bomVersion.Active
&& bomVersion.FromDate <= systemdateget ()
&& (!bomVersion.ToDate || bomVersion.ToDate >= systemdateget ());
if (bomVersion.RecId)
return true ;
return false ;
}
private int InsertParentItem(ItemId _itemId, int _level)
{
InventTable inventTable;
;
//Gets the parent information and then insert on TmpBOMExplode Table with level 0.
select firstOnly inventTable where inventTable.ItemId == _itemId;
tmpBOM.ItemId = _itemId;
tmpBOM.Level = _level;
tmpBOM.BOMQty = 1 ;
tmpBOM.HasChild = this.hasChild(_ItemId);
tmpBOM.insert();
return _level+ 1 ;
}
void itemExplode(ItemId _ItemId, int _level = 0, BOMQty _bomQty = 1)
{
BOM bomTable;
InventTable inventTable;
BOMVersion bomVersion;
InventDim inventDim;
BOMQty qtyS;
;
//Insert parent Item
if (_level == 0)
_level = this.InsertParentItem(_ItemId, _level);
//Verifies if the Item exists in BOMVersion Table.
//The item must be active and not expired.
select firstonly bomVersion
where bomVersion.ItemId == _itemid
&& bomVersion.Active
exists join inventDim
where inventDim.inventDimId == bomVersion.InventDimId &&
(inventDim.InventColorId == inventColorId || inventColorId == "") &&
(inventDim.InventSizeId == inventSizeId || inventSizeId == "");
// && bomVersion.FromDate <= systemdateget()
// && (!bomVersion.ToDate || bomVersion.ToDate >= systemdateget());
if (bomVersion.RecId)
{
//Every item on BOMVersion has a BOMId which is used to show
//which products belong to a BOM Item.
While select bomTable
where bomTable.BOMId == bomVersion.BOMId
join inventTable
where bomTable.ItemId == inventTable.ItemId
{
//Insert the items that compose the BOM Item with level 1.
tmpBOM.ItemId = bomTable.ItemId;
tmpBOM.RefItemId = bomVersion.ItemId;
tmpBOM.BOMQty = bomTable.BOMQty / bomTable.BOMQtySerie * _bomQty;
tmpBOM.Level = _level;
tmpBOM.UnitId = bomTable.UnitId;
tmpBOM.HasChild = this.hasChild(bomTable.ItemId);
tmpBOM.MainItemId = this.parmItemId();
tmpBOM.insert();
//This method is used to check if the BOM Item is composed by
//another BOM Item, case true it will call the method recursively
// with level 2.
if (tmpbom.HasChild == NoYes::Yes)//--- unit conversion ---
{
qtyS = UnitOfMeasureConverter::convert(
tmpBOM.BOMQty,
UnitOfMeasure::unitOfMeasureIdBySymbol(tmpBOM.UnitId),
UnitOfMeasure::unitOfMeasureIdBySymbol(bomTable.inventTable().inventUnitId()),
NoYes::Yes,
InventTable::itemProduct(tmpBOM.ItemId));
this.itemExplode(bomTable.ItemId, _level+ 1, qtyS);
}
}
}
}
void linkTables(SNBBOMExplodeTmp _tmp)
{
tmpBOM.linkPhysicalTableInstance(_tmp);
}
class SNBBOMExplode
{
SNBBOMExplodeTmp tmpBOM;
SNBBOMExplodeData bomdata;
ItemId itemId;
EcoResItemSizeName inventSizeId;
EcoResItemColorName inventColorId;
InventSiteId inventSiteId;
}
boolean hasChild(ItemId _itemId)
{
BOMVersion bomVersion;
;
//Check if the item is also a BOM item.
select firstonly bomVersion
where bomVersion.ItemId == _itemid
&& bomVersion.Active
&& bomVersion.FromDate <= systemdateget ()
&& (!bomVersion.ToDate || bomVersion.ToDate >= systemdateget ());
if (bomVersion.RecId)
return true ;
return false ;
}
private int InsertParentItem(ItemId _itemId, int _level)
{
InventTable inventTable;
;
//Gets the parent information and then insert on TmpBOMExplode Table with level 0.
select firstOnly inventTable where inventTable.ItemId == _itemId;
tmpBOM.ItemId = _itemId;
tmpBOM.Level = _level;
tmpBOM.BOMQty = 1 ;
tmpBOM.HasChild = this.hasChild(_ItemId);
tmpBOM.insert();
return _level+ 1 ;
}
void itemExplode(ItemId _ItemId, int _level = 0, BOMQty _bomQty = 1)
{
BOM bomTable;
InventTable inventTable;
BOMVersion bomVersion;
InventDim inventDim;
BOMQty qtyS;
;
//Insert parent Item
if (_level == 0)
_level = this.InsertParentItem(_ItemId, _level);
//Verifies if the Item exists in BOMVersion Table.
//The item must be active and not expired.
select firstonly bomVersion
where bomVersion.ItemId == _itemid
&& bomVersion.Active
exists join inventDim
where inventDim.inventDimId == bomVersion.InventDimId &&
(inventDim.InventColorId == inventColorId || inventColorId == "") &&
(inventDim.InventSizeId == inventSizeId || inventSizeId == "");
// && bomVersion.FromDate <= systemdateget()
// && (!bomVersion.ToDate || bomVersion.ToDate >= systemdateget());
if (bomVersion.RecId)
{
//Every item on BOMVersion has a BOMId which is used to show
//which products belong to a BOM Item.
While select bomTable
where bomTable.BOMId == bomVersion.BOMId
join inventTable
where bomTable.ItemId == inventTable.ItemId
{
//Insert the items that compose the BOM Item with level 1.
tmpBOM.ItemId = bomTable.ItemId;
tmpBOM.RefItemId = bomVersion.ItemId;
tmpBOM.BOMQty = bomTable.BOMQty / bomTable.BOMQtySerie * _bomQty;
tmpBOM.Level = _level;
tmpBOM.UnitId = bomTable.UnitId;
tmpBOM.HasChild = this.hasChild(bomTable.ItemId);
tmpBOM.MainItemId = this.parmItemId();
tmpBOM.insert();
//This method is used to check if the BOM Item is composed by
//another BOM Item, case true it will call the method recursively
// with level 2.
if (tmpbom.HasChild == NoYes::Yes)//--- unit conversion ---
{
qtyS = UnitOfMeasureConverter::convert(
tmpBOM.BOMQty,
UnitOfMeasure::unitOfMeasureIdBySymbol(tmpBOM.UnitId),
UnitOfMeasure::unitOfMeasureIdBySymbol(bomTable.inventTable().inventUnitId()),
NoYes::Yes,
InventTable::itemProduct(tmpBOM.ItemId));
this.itemExplode(bomTable.ItemId, _level+ 1, qtyS);
}
}
}
}
void linkTables(SNBBOMExplodeTmp _tmp)
{
tmpBOM.linkPhysicalTableInstance(_tmp);
}
EcoResItemColorName parmInventColorId(EcoResItemColorName _inventColorId = inventColorId)
{
inventColorId = _inventColorId;
return inventColorId;
}
EcoResItemSizeName parmInventSizeId(EcoResItemSizeName _inventSizeId = inventSizeId)
{
inventSizeId = _inventSizeId;
return inventSizeId;
}
ItemId parmItemId(ItemId _itemId = ItemId)
{
ItemId = _itemId;
return ItemId;
}
SNBBOMExplodeTmp parmSNBBOMExplodeTmp()
{
select * from tmpBOM;
return TmpBOM;
}
void run()
{
delete_from tmpBOM;
this.itemExplode(ItemId,0);
}
Class'da kullanılan SNBBOMExplodeTmp isimli tempDB tipli tablonun yapısı:
BOMQty BOMQty
HasChild NoYesId
ItemId ItemId
Level BOMLevel
MainItemId ItemId
RefItemId ItemId
UnitId UnitOfMeasureSymbol
Örnek kullanımı:
SNBBOMExplodeTmp tmpBOM;
SNBBOMExplode bomExp = new SNBBOMExplode();
bomExp.parmItemId(list.ItemId);
bomExp.linkTables(tmpBOM);
bomExp.parmInventColorId(list.InventColorId);
bomExp.parmInventSizeId(list.InventSizeId);
bomExp.run();
13 Ekim 2017 Cuma
AX 2012 - Bir Finansal Boyuta Göre Sıralama
AX 2012'de mali boyutlar bir RecId alanında saklı olduğu ve çeşitli tabloları refere ettiği için sıralama olayı biraz karışık. Bunun için işimizi kolaylaştırıcı bir sınıf var:
DimensionProvider dimProvider = new DimensionProvider();
dimProvider.addOrderByAttribute(BorAXJournalTrans_DS.query(),BorAXJournalTrans_DS.query().dataSourceNo(1).name(),
FieldStr(BorAXJournalTrans,DefaultDimension),
DimensionComponent::DimensionAttribute,SortOrder::Ascending,
"Departmanı");
BorAXJournalTrans_DS.executeQuery();
Bu sınıfı kullanmak istemiyorum derseniz bir de şöyle bir seçenek var:
RecId depRecId = 5637152827; //departman boyutunun DimensionAttribute tablosundaki recId değeri
BorAXJournalTrans boraxJournalTrans;
DimensionAttributeValueSet dimensionAttributeValueSet;
DimensionAttributeValueSetItem dimensionAttributeValueSetItem;
DimensionAttributeValue dimensionAttributeValue;
DimensionAttribute dimensionAttribute;
while SELECT firstOnly10 borAXJournalTrans
ORDER BY DimensionAttributeValueSetItem.DisplayValue
JOIN dimensionAttributeValueSet
where borAXJournalTrans.DefaultDimension == dimensionAttributeValueSet.RecId
JOIN dimensionAttributeValueSetItem
where dimensionAttributeValueSet.RecId == dimensionAttributeValueSetItem.DimensionAttributeValueSet
JOIN dimensionAttributeValue
where dimensionAttributeValueSetItem.DimensionAttributeValue == dimensionAttributeValue.RecId
JOIN dimensionAttribute
where dimensionAttributeValue.DimensionAttribute == dimensionAttribute.RecId &&
dimensionAttribute.RecId == depRecId
{
info(dimensionAttributeValueSetItem.DisplayValue);
}
DimensionProvider dimProvider = new DimensionProvider();
dimProvider.addOrderByAttribute(BorAXJournalTrans_DS.query(),BorAXJournalTrans_DS.query().dataSourceNo(1).name(),
FieldStr(BorAXJournalTrans,DefaultDimension),
DimensionComponent::DimensionAttribute,SortOrder::Ascending,
"Departmanı");
BorAXJournalTrans_DS.executeQuery();
Bu sınıfı kullanmak istemiyorum derseniz bir de şöyle bir seçenek var:
RecId depRecId = 5637152827; //departman boyutunun DimensionAttribute tablosundaki recId değeri
BorAXJournalTrans boraxJournalTrans;
DimensionAttributeValueSet dimensionAttributeValueSet;
DimensionAttributeValueSetItem dimensionAttributeValueSetItem;
DimensionAttributeValue dimensionAttributeValue;
DimensionAttribute dimensionAttribute;
while SELECT firstOnly10 borAXJournalTrans
ORDER BY DimensionAttributeValueSetItem.DisplayValue
JOIN dimensionAttributeValueSet
where borAXJournalTrans.DefaultDimension == dimensionAttributeValueSet.RecId
JOIN dimensionAttributeValueSetItem
where dimensionAttributeValueSet.RecId == dimensionAttributeValueSetItem.DimensionAttributeValueSet
JOIN dimensionAttributeValue
where dimensionAttributeValueSetItem.DimensionAttributeValue == dimensionAttributeValue.RecId
JOIN dimensionAttribute
where dimensionAttributeValue.DimensionAttribute == dimensionAttribute.RecId &&
dimensionAttribute.RecId == depRecId
{
info(dimensionAttributeValueSetItem.DisplayValue);
}
9 Ağustos 2017 Çarşamba
AX 2012 - Query'ye tek bir finansal boyut için filtre eklemek
Bunu tabloları ekleyerek yapmaya kalktığınızda bir çok tabloyu birbirine bağlamak zorunda olduğunuzu göreceksiniz. Bunu sizin yerinize yapan DimensionProvider adlı bir sınıf eklenmiş AX 2012'ye:
DimensionProvider dimProvider = new DimensionProvider();
dimProvider.addAttributeRangeToQuery(element.query(),element.query().dataSourceNo(1).name(),
FieldStr(MyTable,DefaultDimension),
DimensionComponent::DimensionAttribute,
OMOperatingUnit::find(depRecId,OMOperatingUnitType::OMDepartment).OMOperatingUnitNumber,
"Departmanı",true);
Bu arada Unknown type: RefRecId gibi bir hata alırsanız sebebi kullandığınız tablodaki EDT'nin yanlış olması olabilir. Benim başıma gelen durumda sorun yerel bir çözümde DefaultDimension field'ına DimensionDefault yerine RefRecId EDT kullanılmasıydı. Sizinkinde RefRecId yerine başka birşey de olabilir. AX orijinal tablosu HcmEmployment tablosunda da böyle bir bug varmış.
DimensionProvider dimProvider = new DimensionProvider();
dimProvider.addAttributeRangeToQuery(element.query(),element.query().dataSourceNo(1).name(),
FieldStr(MyTable,DefaultDimension),
DimensionComponent::DimensionAttribute,
OMOperatingUnit::find(depRecId,OMOperatingUnitType::OMDepartment).OMOperatingUnitNumber,
"Departmanı",true);
Bu arada Unknown type: RefRecId gibi bir hata alırsanız sebebi kullandığınız tablodaki EDT'nin yanlış olması olabilir. Benim başıma gelen durumda sorun yerel bir çözümde DefaultDimension field'ına DimensionDefault yerine RefRecId EDT kullanılmasıydı. Sizinkinde RefRecId yerine başka birşey de olabilir. AX orijinal tablosu HcmEmployment tablosunda da böyle bir bug varmış.
8 Ağustos 2017 Salı
AX 2012 - Dönem kapanış kontrolü
Muhasebe için:
FiscalCalendars::checkModuleIsOpen(SysModule::Ledger, myTable.TransDate,FiscalCalendars::findPeriodByPeriodCodeDate(Ledger::fiscalCalendar(CompanyInfo::find().RecId),myTable.ETGTransDate),false)
veya
select firstOnly period
where transDate >= period.StartDate && transDate <= period.EndDate
exists join ledgerPeriod
where ledgerPeriod.FiscalCalendarPeriod == period.RecId &&
ledgerPeriod.Status != FiscalPeriodStatus::Open;
if (period.RecId != 0)
throw error("Yeni tarih için ilgili mali dönem kapalı!..");
Satış için:
FiscalCalendars::checkModuleIsOpen(SysModule::Sales, CustInvoiceJour.InvoiceDate,FiscalCalendars::findPeriodByPeriodCodeDate(Ledger::fiscalCalendar(CompanyInfo::find().RecId),CustInvoiceJour.InvoiceDate),false)
Stok kapanışı için:
InventClosing::findClosingDate(endmth(InventJournalTrans.TransDate))
FiscalCalendars::checkModuleIsOpen(SysModule::Ledger, myTable.TransDate,FiscalCalendars::findPeriodByPeriodCodeDate(Ledger::fiscalCalendar(CompanyInfo::find().RecId),myTable.ETGTransDate),false)
veya
select firstOnly period
where transDate >= period.StartDate && transDate <= period.EndDate
exists join ledgerPeriod
where ledgerPeriod.FiscalCalendarPeriod == period.RecId &&
ledgerPeriod.Status != FiscalPeriodStatus::Open;
if (period.RecId != 0)
throw error("Yeni tarih için ilgili mali dönem kapalı!..");
Satış için:
FiscalCalendars::checkModuleIsOpen(SysModule::Sales, CustInvoiceJour.InvoiceDate,FiscalCalendars::findPeriodByPeriodCodeDate(Ledger::fiscalCalendar(CompanyInfo::find().RecId),CustInvoiceJour.InvoiceDate),false)
Stok kapanışı için:
InventClosing::findClosingDate(endmth(InventJournalTrans.TransDate))
2 Ağustos 2017 Çarşamba
AX 2012 - Security Development Tool Kaynaklı Derleme Hatası
Security Development Tool yetkilendirme işlemlerini oldukça kolaylaştıran harika bir araç. Ancak bizim başımıza gelen can sıkıcı bir soruna yol açabiliyor. Aşağıdaki hatayı alırsanız bilin ki sebebi bu tool:
Error executing code: SysSecurityRecorder_**** object does not have method 'MenuItemInvoked'.
Konuyla ilgili bulabildiğim tek kaynak Google translate ile fransızcadan ingilizceye çevirerek anlayabildiğim bir blog'du (Şahsen Google Translate'yi türkçe çeviriler için çok başarısız buluyorum). Buradaki iki yöntem de işime yaradı:
1. yöntem: Client bilgisayardaki AOD dosyalarını silmek.
2.yöntem: AX DB'de bu kodu çalıştırınca tek tek tüm clientlarda temizlik yapmaya gerek kalmıyor:
UPDATE SYSSQMSETTINGS SET GLOBALGUID = '{00000000-0000-0000-0000-000000000000}'
Error executing code: SysSecurityRecorder_**** object does not have method 'MenuItemInvoked'.
Konuyla ilgili bulabildiğim tek kaynak Google translate ile fransızcadan ingilizceye çevirerek anlayabildiğim bir blog'du (Şahsen Google Translate'yi türkçe çeviriler için çok başarısız buluyorum). Buradaki iki yöntem de işime yaradı:
1. yöntem: Client bilgisayardaki AOD dosyalarını silmek.
2.yöntem: AX DB'de bu kodu çalıştırınca tek tek tüm clientlarda temizlik yapmaya gerek kalmıyor:
UPDATE SYSSQMSETTINGS SET GLOBALGUID = '{00000000-0000-0000-0000-000000000000}'
7 Temmuz 2017 Cuma
AX 2012 - TempDB ile server metoddan forma veri göndermek
TempDB tablosunda direk parametre ile gönderip doldurmaya çalıştığınızda kayıt gelmediğini göreceksiniz. Kayıtların gelmesi için ya In Memory tablo türünü seçmelisiniz ya da linkPhysicalTableInstance metodu ile iki TempDB tablosunu birbirine bağlamalısınız:
Class:
public static server void populateData(MyTempTable _tmp)
{
MyTempTable tmp;
...
...
tmp.linkPhysicalTableInstance(_tmp);
...
...
return;
}
Form:
MyClass::populateData(MyTempTable);
MyTempTable_DS.research();
MyTempTable_DS.refresh();
Class:
public static server void populateData(MyTempTable _tmp)
{
MyTempTable tmp;
...
...
tmp.linkPhysicalTableInstance(_tmp);
...
...
return;
}
Form:
MyClass::populateData(MyTempTable);
MyTempTable_DS.research();
MyTempTable_DS.refresh();
4 Ocak 2017 Çarşamba
AXAPTA - Tabloları eşitle
İş arkadaşımın internetten bulduğu kod, kaynağını bilmiyorum ama birçok durumda işe yarıyor:
Dictionary dict;
int idx, lastIdx, totalTables;
TableId tableId;
Application application;
SysOperationProgress progress;
StackBase errorStack;
ErrorTxt errorTxt;
;
application = new Application();
dict = new Dictionary();
totalTables = dict.tableCnt();
progress = new SysOperationProgress();
progress.setTotal(totalTables);
progress.setCaption("@SYS90206");
errorStack = new StackBase(Types::String);
lastIdx = 3000;
try
{
for (idx = lastIdx+1; idx <= totalTables; idx++)
{
tableId = dict.tableCnt2Id(idx);
progress.setText(dict.tableName(tableId));
lastIdx = idx;
application.dbSynchronize(tableId, false, true, false);
progress.incCount();
}
}
catch (Exception::Error)
{
errorTxt = strFmt("'%1' (%2) tablosunda hata var!", tableId, dict.tableName(tableId));
errorStack.push(errorTxt);
retry;
}
setPrefix("@SYS86407");
errorTxt = errorStack.pop();
while (errorTxt)
{
error(errorTxt);
errorTxt = errorStack.pop();
}
Dictionary dict;
int idx, lastIdx, totalTables;
TableId tableId;
Application application;
SysOperationProgress progress;
StackBase errorStack;
ErrorTxt errorTxt;
;
application = new Application();
dict = new Dictionary();
totalTables = dict.tableCnt();
progress = new SysOperationProgress();
progress.setTotal(totalTables);
progress.setCaption("@SYS90206");
errorStack = new StackBase(Types::String);
lastIdx = 3000;
try
{
for (idx = lastIdx+1; idx <= totalTables; idx++)
{
tableId = dict.tableCnt2Id(idx);
progress.setText(dict.tableName(tableId));
lastIdx = idx;
application.dbSynchronize(tableId, false, true, false);
progress.incCount();
}
}
catch (Exception::Error)
{
errorTxt = strFmt("'%1' (%2) tablosunda hata var!", tableId, dict.tableName(tableId));
errorStack.push(errorTxt);
retry;
}
setPrefix("@SYS86407");
errorTxt = errorStack.pop();
while (errorTxt)
{
error(errorTxt);
errorTxt = errorStack.pop();
}
Kaydol:
Kayıtlar (Atom)