Archive for the ‘ x++ ’ Category

Satınalma talep konsolidasyonu (PurchReqConsolidation) formu performans sorunu

Merhaba,

Bir müşterimizde Satınalma talep konsolidasyonu formu çok geç açılıyordu. Öncelikle sorunun ne olduğunu anlamadım. Formun veri kaynağında yavaşlığa sebep olacak bir tablo yoktu. Indexler düzgün bağlantılarda sorun yok. Formun açılışına yazılmış bir kod yok. Bir süre inceledikten sonra Partları gördüm. Partların kodunu inceleyince sorunu hemen tespit ettim.

public void linkActive()
{
    PurchReqConsolidationLine   purchReqConsolidationLine;
    PurchReqLine                purchReqLine;

    purchReqConsolidation = element.args().record();

    super();

    delete_from purchReqTmpConsolidationPart;

    while select purchReqConsolidationLine
    {
        purchReqLine = PurchReqLine::find(purchReqConsolidationLine.PurchReqLineID);

        purchReqTmpConsolidationPart.PurchReqConsolidationLine = purchReqConsolidationLine.RecId;
        purchReqTmpConsolidationPart.PurchReqConsolidationID   = purchReqConsolidationLine.PurchReqConsolidationId;
        purchReqTmpConsolidationPart.AmountBeforeConsolidation = purchReqConsolidationLine.calcAmountBeforeConsolidation();
        purchReqTmpConsolidationPart.AmountAfterConsolidation  = purchReqConsolidationLine.calcAmountAfterConsolidation();
        purchReqTmpConsolidationPart.VendAccount               = purchReqConsolidationLine.NewVendor;
        purchReqTmpConsolidationPart.setDataAreaForModifiedField(fieldNum(PurchReqTmpConsolidationPart, VendAccount), purchReqLine.buyingLegalEntity2DataArea());
        purchReqTmpConsolidationPart.CurrencyCode              = purchReqLine.CurrencyCode;
        purchReqTmpConsolidationPart.doInsert();
    }

    this.executeQuery();
    this.research();
}

Part formlarından biri olan PurchReqConsolidationPartByVendor formunun LinkActive metoduna yazılan koddaki temel hatayı hemen anlamışsınızdır. join yazılması gereken yerde find kullanılmış. Partları aktif olarak kullanmadığı için bu formdan kaldırıp formun çok daha hızlı açılmasını sağladım.

Daha vahim bir durum Satınalma talep konsolidasyonu formundan bir buton ile açılan PurchReqConsolidationAddLine formunda vardı.

PurchReqConsolidationAddLine Formunun PurchReqLine veri kaynağının init metodunda aşağıdaki kod mevcut.

public void init()
{
    PurchReqLine            tmpPurchReqLine;
    PurchReqTable           tmpPurchReqTable;
    QueryBuildRange         qbr;

    super();

    qbr = purchReqLine_ds.query().dataSourceTable(tableNum(PurchReqLine)).addRange(fieldNum(PurchReqLine,RequisitionPurpose));
    qbr.value(SysQuery::value(RequisitionPurpose::Consumption));
    qbr.status(RangeStatus::Locked);

    qbr = purchReqLine_ds.query().dataSourceTable(tableNum(PurchReqLine)).addRange(fieldNum(PurchReqLine,PurchLineCreated));
    qbr.value(SysQuery::value(NoYes::No));
    qbr.status(RangeStatus::Locked);

    qbr = purchReqLine_ds.query().dataSourceTable(tableNum(PurchReqLine)).addRange(fieldNum(PurchReqLine,RequisitionStatus));
    qbr.value(queryValue(PurchReqRequisitionStatus::Approved));
    qbr.status(RangeStatus::Locked);

    purchReqLine.setTmp();

    while select tmpPurchReqLine
            join RecId, SourceDocumentHeader   from tmpPurchReqTable
           where tmpPurchReqLine.PurchReqTable            == tmpPurchReqTable.RecId   &&
                 tmpPurchReqLine.IsPreEncumbranceRequired != UnknownNoYes::Unknown
    {
        if (PurchReqPurchaseOrderGenerationRule::canConsolidateStatic(tmpPurchReqLine) &&
            !PurchReqConsolidationLine::findByReqLineId(tmpPurchReqLine.RecId))
        {
            purchReqLine.data(tmpPurchReqLine.data());

            // Since tempory table will overwrite the RecId value, so assign RecId into an unused field
            purchReqLine.AddressRefRecId = tmpPurchReqLine.RecId;

            purchReqLine.doInsert();
        }
    }
}

PurchReqConsolidationLine join yerine if ile kontrol edildiği için bu formun açılması da dakikalar sürüyordu. Kodu aşağıdaki hale çevirince saniyeler içinde açılmaya başladı.

public void init()
{
    PurchReqLine            tmpPurchReqLine;
    PurchReqTable           tmpPurchReqTable;
    purchReqConsolidationLine purchReqConsolidationLine;
    QueryBuildRange         qbr;

    super();

    qbr = purchReqLine_ds.query().dataSourceTable(tableNum(PurchReqLine)).addRange(fieldNum(PurchReqLine,RequisitionPurpose));
    qbr.value(SysQuery::value(RequisitionPurpose::Consumption));
    qbr.status(RangeStatus::Locked);

    qbr = purchReqLine_ds.query().dataSourceTable(tableNum(PurchReqLine)).addRange(fieldNum(PurchReqLine,PurchLineCreated));
    qbr.value(SysQuery::value(NoYes::No));
    qbr.status(RangeStatus::Locked);

    qbr = purchReqLine_ds.query().dataSourceTable(tableNum(PurchReqLine)).addRange(fieldNum(PurchReqLine,RequisitionStatus));
    qbr.value(queryValue(PurchReqRequisitionStatus::Approved));
    qbr.status(RangeStatus::Locked);
    purchReqLine.setTmp();

    while select tmpPurchReqLine
            join RecId, SourceDocumentHeader   from tmpPurchReqTable
           where tmpPurchReqLine.PurchReqTable            == tmpPurchReqTable.RecId   &&
                 tmpPurchReqLine.IsPreEncumbranceRequired != UnknownNoYes::Unknown
        // Dmr FD -->
        notExists join purchReqConsolidationLine
            where tmpPurchReqLine.RecId ==  purchReqConsolidationLine.PurchReqLineID
        // Dmr FD <--

    {
        // Dmr FD -->
        //if (PurchReqPurchaseOrderGenerationRule::canConsolidateStatic(tmpPurchReqLine) &&
           // !PurchReqConsolidationLine::findByReqLineId(tmpPurchReqLine.RecId))
        if (PurchReqPurchaseOrderGenerationRule::canConsolidateStatic(tmpPurchReqLine) )
        // Dmr FD <--
        {
            purchReqLine.data(tmpPurchReqLine.data());

            // Since tempory table will overwrite the RecId value, so assign RecId into an unused field
            purchReqLine.AddressRefRecId = tmpPurchReqLine.RecId;

            purchReqLine.doInsert();
        }
    }
}

İki kod arasındaki farkı şöyle özetleyebilirim. İlk hali bütün PurchReqLine ları dolanıp PurchReqConsolidationLine da olmayanlar için temp kayıt oluşturur.
İkinci hali ise NotExists join ile bağlandığı için zaten sadece PurchReqConsolidationLine olmayan PurchReqLine ları getirecektir. Dolayısıyla çok daha hızlı olacaktır.

Performans ERP yazılımında belkide en çok dikkat edilmesi gereken konulardan biri. Yazdığımız her kodun birilerinin günlük hayatı olduğunu anlayıp mümkün olduğunda performanslı olmasına dikkat etmek gerekiyor. Gördüğünüz gibi çok basit dokunuşlarla çok büyük kazanımlar elde edebiliyorsunuz. Burada standart kodda böyle bir hatayla karşılaşmak beni şaşırttı. Genelde Standart kod çok kalitelidir ama bazen böyle gözden kaçan kodlar da olabiliyor.

Selamlar.

Muhasebe günlük satırlarından bir alanı tedarikçi açık hareketlerine taşımak

Merhaba

Muhasebe günlük satırlarından (LedgerJournalTrans) bir alanı Tedarikçi hareketlerine (VendTrans) ve Tedarikçi açık hareketlerine (VendTransOpen) taşımak için aşağıdaki adımları takip edebilirsiniz.

  1. LedgerJournalTrans.DmrWfId taşımak istediğimiz alan.
  2. VendTrans, VendTransOpen tablolarına ve  CustVendTrans mapine DmrWfId alanı açılır.
  3. LedgerJournalTransDaily formuna DmrWfId alanı eklenip veri girilmesi sağlanır.
  4. VendVoucher clasının post() metoduna  _vendTrans.DmrWfId   =  ledgerJournalTrans.DmrWfId; satırı eklenir.
  5. VendVoucherJournal clasının initCustVendTrans() metoduna vendTrans.DmrWfId = ledgerJournalTrans.DmrWfId; satırı eklenir.
  6. VendVoucher clasının createTransOpen() metoduna  vendTransOpen.DmrWfId  = _custVendTrans.DmrWfId; satırı eklenir.

Bu adımlarla DmrWfId alanını istediğimiz tablolara taşımış olduk.

Selamlar.

AutoRefreshData property on buttons AX2012

Merhaba,

Ax gerçekten bir çok ayrıntıya sahip. Özellikle nesnelerin özelliklerinde aktif olarak kullanmadığımız bir çok yenilik mevcut. AutoRefreshData özelliği de bunlardan biri.

Yaptığım bir geliştirmede ListePage formunda durum değiştiren bir sınıf yaptım. Bildiğiniz gibi ListPage formlara kod yazamıyoruz. Bu sınıf ListePage’teki satırın durum alanını değiştiriyor. Bu değişikliği yaptıktan sonra formu yenilemem gerekiyordu. Bunu yapmak için args üzerinde DateSource alıp üzerinden Refresh çalıştırmak gerekiyor ama güzel bir yöntem değil. Bunun daha kolay bir çözümü olmalı derken buton üzerindeki AutoRefreshData özelliğini gördüm. Bu özelliği true olarak ayarlağınızda aslında Table_DS.Research(True) metodunun yaptığı işi yapıyor. Bu sayede kod yazmadan griddeki veriyi güncelleniyor.

Selamlar.

How to get table field properties from X++

Hi,

Sometimes while development process you need to get table field properties. One of my customer i need to setup a structure which i have to get all the LedgerJournalTrans table fields names and properties .

In this example i loop all the fields except some system fields and  show names and some properties.


//Dmr Fatih Demirci
static void Dmr_FD_GetTableField(Args _args)
{
    SysDictTable    dictTable = new SysDictTable(tableNum(LedgerJournalTrans));
    SysDictField    dictField;
    TreeNode        treeNode;
    FieldId         fieldId   = dictTable.fieldNext(0);
    ;

    while (fieldId)
    {
        dictField = dictTable.fieldObject(fieldId);

        //Except Sql, System, visible fields
        if (   dictField.isSql()      && !dictField.isSystem()
            && dictField.allowEdit()  && dictField.allowEditOnCreate()
            && dictField.visible()    && !dictField.getCountryRegionCodes( ) )
        {
            treeNode = dictField.treeNode();

            info(strFmt("%1-%2-%3-%4",  dictField.id(),
                                        dictField.name() ,
                                        dictField.label(),
                                        dictField.baseType()  ));
        }

        fieldId = dictTable.fieldNext(fieldId);
    }
}

Info:

Happy Daxing.

Ax 2012′de sabit muhasebe boyut değerleri nasıl tanımlanır (Fixed Dimensions)

Merhaba,

Bu yazımda muhasebe boyut yapısında hesaplar için sabit boyut değerlerinin nasıl tanımlandığından bahsedeceğim. Ax2012′de muhasebe hesapları MainAccount tablosunda şirketler üstü tutuluyor. Birden çok hesap planı tanımlayabiliyorsunuz. Şirketler için bazı özel tanımlar mevcut bunları yapmak istediğinizde aşağıdaki resimde olduğu gibi istediğiniz şirketleri eklemeniz gerekiyor.

Görüntülenecek ana hesap düzeyi seçin kısmından Şirketler’i seçtiğinizde istediğiniz şirketi ekleyebileceğiniz ve daha önce eklediğiniz şirketleri görebileceğiniz kısımlar açılıyor.

Herhangi bir şirketin üzerine geldiğinizde Mali boyutlar (Default Dimension) sekmesi açılır.

Burada görüldüğü gibi mali boyutlar seçilebilir. Ayrıca her bir boyutun karşısında bu boyut değerinin Sabit mi değil mi olduğunu belirleyebildiğimiz kısım açılır. Burada yapılan tanımlamanın ne manaya geldiğini şöyle özetleyebilirim. Örneğin 112120 hesabı için USMF şirketinde GiderGrupları mali boyut her zaman  G001 olmak zorundadır. Eğer muhasebeye kayıt oluşurken G001 haricinde bir değer gelirse sistem G001 ile güncelleyip muhasebe kaydını öyle oluşturur. Proje ve ürün tipi boyutlarında ise farklı bir değer  bile gelse bir değişiklik yapmaz.

Şimdi bu tanımların veri yapısının nasıl olduğunu inceleyelim.

Kullanılan BaseEnum.

Bu tablo muhasebe hesaplarını şirket bazında farklılaşan verilerini tutar. Yukarıda anlatıldığı gibi şirket eklendiğinde burada kayıt oluşur.

Görüldüğü gibi bir DefaultDimension birde FixedDimension alanı mevcut. DefaultDimension bildiğimiz muhasebe boyutlarıdır. FixedDimension ise bu boyutların Sabit mi değil mi olduğunu tutan yapıdır. DefaultDimension DimensionAttributeValueSet tablosuna bağlıyken FixedDimension ise DimensionAttributeSet bağlıdır.

Sabit boyut değerlerini tutan tablodur.

Sabit boyut değerlerinin satırları tutan tablodur. EnumerationValue alanında yukarıda bahsi geçen DimensionFixed enum değeri tutulur. 1 sabit değer manasına gelmektedir.

Hangi mali boyut olduğunu tutan tablodur.

Bu yapıyı kavradıktan şöyle bir örnek yapalım. Hesap planında Gider grupları diye bir alanımız olsun. Bu alandan bir değer seçilip kaydedildiğinde o muhasebe hesabı için her bir aktif şirket  ile ilişkili bir kayıt oluşturup GiderGrupları muhasebe boyutuna bu kodu yazsın ve bu değeri de sabit değer olarak işaretlesin.

Öncelikle MainAccountLegalEntity kayıtlarını oluşturacak metodu yazalım.

public static void dmrCreateMainAccountLegalEntity(MainAccount _mainAccount )
{
    CompanyInfo                         companyInfoList;
    Ledger                              ledgerList;
    MainAccountLegalEntity              mainAccountLegalEntityList;
    DimensionAttrValueLedgerOverride    dimensionAttrValueLedgerOverride;
    MainAccountLegalEntity              MainAccountLegalEntity;
    container   conDimAtr;
    container   conValue;
    ;
    // Todo FD Boyutları parametrik yapmalıyız.
    conDimAtr = ["GiderGruplari","Project","ÜrünTipi"];
    conValue  = [1,0,0];

     while select DataArea from companyInfoList
        join RecId from ledgerList
            where ledgerList.PrimaryForLegalEntity == companyInfoList.RecId &&
                ledgerList.ChartOfAccounts == _mainAccount.LedgerChartOfAccounts
        notexists join RecId from mainAccountLegalEntityList
            where mainAccountLegalEntityList.LegalEntity == companyInfoList.RecId &&
                mainAccountLegalEntityList.MainAccount == _mainAccount.RecId
    {
        MainAccountLegalEntity.clear();
        MainAccountLegalEntity.MainAccount          = _mainAccount.RecId;
        MainAccountLegalEntity.LegalEntity          = companyInfoList.RecId;
        MainAccountLegalEntity.DefaultDimension     = AxdDimensionUtil::DmrGetNewDefaultDimension(0
                                                    , "GiderGruplari" , _mainAccount.DmrExpsGroupId);
        MainAccountLegalEntity.FixedDimensions      = AxdDimensionUtil::DmrFindOrCreateFixedDimension(
                                                        conDimAtr, conValue);

        MainAccountLegalEntity.insert();
    }
}

DimensionAttributeSet kayıtlarını oluşturmak için sistemde bulunan DimensionAttributeSetStorage sınıfından faydalanıyoruz.

public static DimensionDefault DmrFindOrCreateFixedDimension( container   _conAttr
                                                             ,container   _conValue)
{
    DimensionAttributeSetStorage   valueSetStorage = new DimensionAttributeSetStorage();
    DimensionDefault               result;
    int                     i;
    DimensionAttribute      dimensionAttribute;
    boolean                 dimValue;
    ;

    for (i = 1; i <= conLen(_conAttr); i++)
    {
        dimensionAttribute = dimensionAttribute::findByName(conPeek(_conAttr,i));

        if (dimensionAttribute.RecId == 0)
        {
            continue;
        }

        dimValue = conPeek(_conValue,i);
        valueSetStorage.addItem(dimensionAttribute.RecId
                        ,dimensionAttribute.HashKey ,dimValue);
    }
    result = valueSetStorage.save();
    return result;
}

Her farklı kombinasyon için DimensionAttributeSet tablosunda yeni bir kayıt oluşmaktadır. Eğer aynı kombinasyon varsa o kaydı geri döndürür.

Selamlar.

Proje ücret günlüğü oluşturmak

Merhaba

Bu yazımda proje modulunde bulunan ücret günlüğünün kodla nasıl oluşturulacağını anlatacağım. Bu örnekte bir temp tablom var. Tablonun yapısı aşağıdaki gibi.

Bu tablonun içerisine tipi ücret olan proje kategorilerini otomatik oluşturuyorum ve kullanıcının miktar ve fiyat girmesinden sonra bu tabloyu kullanarak bir sınıf yardımıyla proje günlüğünü oluşturuyorum.

Günlüğü oluşturduğum metot;


void fdCreateProjJournal()
{
    ProjJournalTableData    JournalTableData;
    ProjJournalTransData    journalTransData;
    ProjJournalTable        journalTable;
    ProjJournalTrans        journalTrans;
    DmrProjInvoiceTmp       tmp;       // Parm metotla sınıfa aktarıldı
    TransDate               transDate; // Parm metotla sınıfı aktarıldı
    ProjTable               projTable; // Parm metotla sınıfa aktarıldı

;
    ttsBegin;

    journalTableData = JournalTableData::newTable(journalTable);
    journalTransData = journalTableData.journalStatic().newJournalTransData(
       journalTrans,journalTableData);
    journalTable.clear();
    journalTable.JournalId      = journalTableData.nextJournalId();
    journalTable.JournalType    = ProjJournalType::Revenue;
    journalTable.JournalNameId  = ProjParameters::find().RevenueJournalNameId;

    while select tmp
        where tmp.Amount != 0
    {
        journalTableData.initFromJournalName(
         journalTableData.journalStatic().findJournalName(journalTable.JournalNameId));

        journalTrans.clear();
        journalTransData.initFromJournalTable();
        journalTrans.TransDate          = transDate;
        journalTrans.ProjTransDate      = transDate;
        journalTrans.ProjId             = projTable.ProjId;
        journalTrans.Qty                = tmp.Qty;
        journalTrans.SalesPrice         = tmp.Amount;
        journalTrans.CostPrice          =  1;
        journalTrans.Txt                = projTable.psaRetainageBillingDesc();
        journalTrans.CurrencyId         = ProjInvoiceTable::find(
                     projTable.ProjInvoiceProjId).CurrencyId;
        journalTrans.Worker             = HcmWorker::userId2Worker(curUserId());
        journalTrans.CategoryId         = tmp.ProjCategoryId;
        journalTrans.LinePropertyId     = ProjCategory::find(
                   tmp.ProjCategoryId).projLinePropertyId();
        journalTrans.DefaultDimension   = projTable.DefaultDimension;

        journalTransData.create();
    }
    journalTable.insert();

    info(strFmt("%1 nolu günlük oluşturuldu.", journalTable.JournalId));

    this.projJournalPost();
    ttsCommit;

}

Günlüğü defetere nakletmek için yazdığım metot:

void projJournalPost( )
{
    ProjJournalCheckPost jourPost;
    jourPost = ProjJournalCheckPost::newJournalCheckPost(true,true,
                JournalCheckPostType::Post, tableNum(ProjJournalTable),
                journalTable.JournalId);
    jourPost.run();
}

Bu sayede günlüğü oluşturup deftere nakil işlemini de yapmış oluyoruz. Oluşan günlüğü Proje modülü altında günlükler ücret günlüğünden görebilirsiniz.

Selamlar.

Dynamics AX’ta BCC (Gizli) mail nasıl gönderilir?

Merhaba

Ax içinden Bcc mail göndermek için SYSMailer sınıfına bazı eklemeler yapmak gerekiyor.

Aşağıdaki metotları SYSMailer sınıfına ekleyelim.

//DMR FD
SysMailerAddressField bccs()
{
    InteropPermission permission = new InteropPermission(InteropKind::ComInterop);

    permission.assert();

    //BP Deviation Documented
    return SysMailerAddressField::create(_com,SysmailerAddressFieldType::Bcc);
}

.

// DMR FD
SysMailerAddressField tosBCC()
{
    ;
    return SysMailerAddressField::create(_com,SysmailerAddressFieldType::Bcc);
}

.

// DMR FD
public void quickSendBcc(str fromAddr, str toAddr, str subject,
 str body, str cc='',str bcc='', str attachments='')
{
    SysMailerAddressField tos;
    SysMailerAddressField ccs;
    SysMailerAddressField bccs;
    SysMailerAttachments mailAttachments;
    SysEmailParameters parameters;

    List emailAddresses;
    ListEnumerator enum;
    ;

    this.fromAddress(fromAddr);

    tos = this.tos();
    emailAddresses = SysEmailDistributor::splitEmail(toAddr);
    enum = emailAddresses.getEnumerator();
    while(enum.moveNext())
    {
        tos.appendAddress(enum.current());
    }

    this.subject(subject);
    this.htmlBody(body);

    if (!prmisdefault(cc))
    {
        ccs = this.ccs();
        ccs.appendAddress(cc);
    }

    if (!prmisdefault(bcc))
    {
        bccs = this.bccs();
        bccs.appendAddress(bcc);
    }

    if (!prmisdefault(attachments))
    {
        mailAttachments = this.attachments();
        mailAttachments.add(attachments);
    }

    this.priority(1);

    parameters = SysEmailParameters::find();

    if (parameters.smtpRelayServerName)
    {
        this.SMTPRelayServer(parameters.smtpRelayServerName,parameters.smtpPortNumber,
              parameters.smtpUserName,SysEmailParameters::password(),parameters.ntlm);
    }

    this.sendMail();

}

Bu eklemelerde sonra şöyle bir örnekle mail gönderimini test edebiliriz.

static void FD_SendMailSampleCcandBcc(Args _args)
{
    SysMailer   mailer;
    str         toEmail     = "fatih.demirci@aaaa.com";
    str         fromEmail   = "iletisim@aaaa.com";
    str         cc          = "aaaaa@aaaa.com";
    str         bcc         = "bbbb@aaaa.com";
    str         subject     = "Email konusu";
    str         body        = "Email içeriği";

    ;
    mailer = new SysMailer();
    mailer.quickSendBcc( fromEmail, toEmail, subject, body, cc , bcc);

}

Selamlar.

Proje teklif satırından otomatik WBS kaydı oluşturmak (AX 2012)

Merhaba

Ax 2012′de proje tekliflerini girerken teklif satırından otomatik WBS satırlarının oluşturulması için yazdığım metodu sizinle paylaşıyorum.

Bu metot sayesinden wbs ve teklif arasından etkileşimi sağlamış oluyoruz.

void addItemToWBS()
{
    PSAActivityEstimates    estimates;
    Hierarchy               hierarchy;
    HierarchyIdBase         hierarchyId;
    HierarchyTreeTable      hierarchyTreeTable;
    ;
    hierarchyId = HierarchyLinkTable::findRefTableRecId(tablenum(SalesQuotationTable),
                SalesQuotationTable.RecId).HierarchyId;
    hierarchyTreeTable   = HierarchyTreeTable::findbyNameonHierarchy(hierarchyId ,
           "FD_AnaKategori"); // Hangi kategoriye bağlanacak
    smmActivities      = smmActivities::find(hierarchyTreeTable.activityNumber());

    estimates.clear();
    estimates.ActivityNumber     = smmActivities.ActivityNumber;
    estimates.initFromInventTable(InventTable);
    estimates.InventDimId        = SalesQuotationLine.inventDimId;
    estimates.ItemId             = SalesQuotationLine.ItemId;
    estimates.ProjCategoryId     = SalesQuotationLine.ProjCategoryId;
    estimates.Quantity           = SalesQuotationLine.SalesQty;
    estimates.ProjTransType      = SalesQuotationLine.ProjTransType;
    estimates.Worker             = SalesQuotationLine.ProjectWorker;
    estimates.UnitSalesPrice     = SalesQuotationLine.SalesPrice;
    estimates.UnitCostPrice      = SalesQuotationLine.CostPrice;
    estimates.TotalSalesPrice    = SalesQuotationLine.LineAmount;
    estimates.TotalCostPrice     = SalesQuotationLine.SalesQty * SalesQuotationLine.CostPrice;
    estimates.LinePropertyId     = SalesQuotationLine.LinePropertyId;
    estimates.Description        = SalesQuotationLine.ProjDescription;
    estimates.PRGSalesUnit       = SalesQuotationLine.SalesUnit;
    estimates.insert();

    ttsBegin;
    SalesQuotationLine.selectForUpdate(true);
    SalesQuotationLine.PSARefRecId  = estimates.RecId;
    SalesQuotationLine.doUpdate();
    ttsCommit;

}

Update ve Delete kodları SalesQuotationLine içinde psaUpdateActivityEstimates() ve psaDeleteActivityEstimates() adiyla mevcut. Sistem bunları kullanıyor.

Selamlar.

Stok hareketine kodla rezervasyon koymak

Merhaba

Uzun zamandır fırsat bulup yeni yazı yazamıyordum. Canlıya geçiş yoğunlu sonra iş değişikliği derken zaman çok hızlı geçti. Yeni işimle birlikte farklı konularda da yazılar yazmayı planlıyorum.

Bu yazımda koddan bir stok hareketine nasıl rezervasyon koyulabileceğini anlatacağım.  Bu örnekte SalesLine’nın stok hareketi var ancak SalesQoutationLine gibi farklı tablolar da olabilir. Rezervasyonu eldeki stoğa veya satın almaya koyabilirsiniz. Formdan rezervasyon koymak için satış formunu açıp satırlardan / Stok/ Rezervasyon menüsünden açılan formda, Rezervasyon sütununa istediğiniz miktarı yazarak yapabilirsiniz.

Eğer bu işlemi koddan yapmak istersek aşağıdaki gibi bir kod işimizi görecektir.

  DMRSalesQuotationControl::inventReservation(Salesline.InventTransId ,
        "", SalesLine.SalesQty , false ,true);

Server Static void inventReservation(   InventTransId   _inventTransId,
                                           InventSerialId  _inventSerialId,
                                           Qty             _qty ,
                                           boolean         _unreserve = false ,
                                           boolean         _allowReserveOrdered = false)
{
    InventUpd_Reservation   inventUpd_Reservation;
    inventMovement          inventMovement;
    InventSerial            invserial;
    inventdim               inventDim,iDimNew;
    SalesLine               salesLine;
    ;
    ttsbegin;
    salesLine = SalesLine::findInventTransId(_inventTransId);
    if (!salesline)
    {
        throw error("Sales order line could not be found !");
    }
    inventDim                = salesLine.inventDim();
    inventdim.inventSerialId = _inventSerialId;
    iDimNew                  = inventDim::findOrCreate(inventDim);

inventMovement =InventTrans::findTransId(salesLine.InventTransId).inventMovement(true);
    if(inventMovement)
    {
        inventUpd_Reservation = InventUpd_Reservation::newInventDim(inventMovement,
               iDimNew, _unreserve ? _qty : -_qty);
        // if there is not enough inventory make rezervation from Purchase order.
        inventUpd_Reservation.parmAllowReserveOrdered(_allowReserveOrdered);
        inventUpd_Reservation.updateNow();
    }
    ttscommit;

}

Ax 2009 ve Ax 2012 aynı kod çalışıyor.

Selamlar.

Gönderme panosunda çalışan ismini göstermek.

Merhaba

AX 2012′de Hizmet yönetimi/ Gönderme panosu (SMADispatchBoard) formunda sadece çalışan kodu gösteriliyor. Kod üzerinde bir süre durursanız çalışanın adını da gösteriyor. Buradan iş ataması yapacak kişilerin bütün kodları bilmesi mümkün değil. Altyapı olarak ActiveX kullanıldığı için direk değiştiremiyoruz. Çalışan ismini göstermek için veriyi dolduran sınıfta ufak bir değişiklik yapmak gerekiyor.

GanttVcDataTable sınıfının  createUserDefinedRecord() metoduna  // FD aralığındaki kodu eklemek yeterli olacaktır.

        else
        {
            if(_mapInsertedFields && _mapInsertedFields.exists(ganttVcDataTableField.parmFieldName()))
            {
                strFieldValue = _mapInsertedFields.lookup(ganttVcDataTableField.parmFieldName());
                // FD
                if(HcmWorker::findByPersonnelNumber(strFieldValue))
                {
                    strFieldValue = HcmWorker::findByPersonnelNumber(strFieldValue).name() ;
                }
                // FD
            }
        }

Selamlar.

Page 1 of 141234510...Last »