Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Finance | Project Operations, Human Resources, ...
Answered

Create batch job through X++ code

(0) ShareShare
ReportReport
Posted on by 384

Dear Gentlemen,

i am creating a new batch job using x++ code, using the below code:

class IS_BatchClassTEst extends RunBaseBatch

{

  boolean canGoBatchJournal()
    {
        return true;
    }

    public container pack()
    {
        return conNull();
    }

    //Returns the stored object for the batch to use
    public boolean unpack(container packedClass)
    {
        return true;
    }

    //Determines whether to run on server or client
//True - Server; False - Client
    public boolean runsImpersonated()
    {
        return true;
    }

    public void Run()
    {
      //  info("Batch WOrking");
    }

}

I was able to retrieve the class in Microsoft dynamics 365 but the code isn't executing.

When the status is ended, i don't get the results ( let's say an info message saying Batch Working).

can you please advise if i am missing something ? And if i can  use main(Args _args) instead of run () ?

Regards,

  • sylvesterPowerBi Profile Picture
    384 on at
    RE: Create batch job through X++ code

    Thank You Sir.

  • Verified answer
    nmaenpaa Profile Picture
    101,158 Moderator on at
    RE: Create batch job through X++ code

    One more thing, please use the code formatting when you share your code, so that it's easier to read.

    You can reach it by "Use rich text formatting -> Insert -> Insert Code

    This time I did it for you.

    Looking at your code, it seems that you ignored our earlier comments. Please read our earlier posts again.

    Here's a summary of them:

    In main method, you must call prompt() which shows the batch dialog.

    Then you must call run to run the actual batch logic.

    Please check class Tutorial_RunBaseBatch in AOT.

  • sylvesterPowerBi Profile Picture
    384 on at
    RE: Create batch job through X++ code

    Below is my full class:

    public class IS_RetailStatementJournalShortage extends RunBaseBatch
    {        
               /// 
       /// Runs the class with the specified arguments.
       /// 
       /// The specified arguments.
       public static void main(Args _args)
       {  
           RetailPosBatchTable     retailPosBatchTable;
           RetailTransactionTable  retailTransactionTable;
           RetailParameters        retailParameters;
           int counter = 0;
           NoYes posted = NoYes::No;
           LedgerJournalTable journalTable;
           LedgerJournalTrans journalTrans;
           LedgerJournalName   journalName;
           container                           _acctPattern;
           container                           _offSetAcctPattern;
           NumberSeq                           numberSeq;
           Voucher                             voucher;
           ledgerJournalCheckPost               ledgerJournalCheckPost;
           // Create journal
           ttsbegin;
           retailParameters = RetailParameters::find();
           journalName = LedgerJournalName::find(retailParameters.IS_LedgerJournalNameID);
           journalTable.clear();
           journalTable.initValue();
           JournalTable.initFromLedgerJournalName(journalName.JournalName);
           journalTable.Name = journalName.Name;
           journalTable.JournalName = journalName.JournalName;
           journalTable.insert();
           while select forupdate retailPosBatchTable where retailPosBatchTable.IS_Shortage == NoYes::No /*&& retailPosBatchTable.CloseDate >= str2DateDMY("01/08/2019")*/
           {
               posted = NoYes::No;
               if(retailPosBatchTable.Posted == NoYes::Yes && retailPosBatchTable.StatementId != "")
               {
                   posted = NoYes::Yes;
               }
               else if(retailPosBatchTable.Posted == NoYes::No)
               {
                   while select retailTransactionTable where retailTransactionTable.BatchID == retailPosBatchTable.BatchID && retailTransactionTable.store == retailPosBatchTable.StoreId && retailTransactionTable.BatchTerminalId == retailPosBatchTable.TerminalId
                   {
                       if(retailTransactionTable.entryStatus == RetailEntryStatus::Posted)
                       {
                           posted = NoYes::Yes;
                           break;
                       }
                   }
               }
               if(posted == NoYes::Yes)
               {
                   if(retailPosBatchTable.overAmountTotal() == 0)
                       continue;
                   else if(retailPosBatchTable.overAmountTotal() > 0)
                   {
                       var s = new IS_RetailStatementJournalShortage();
                       JournalTrans.LedgerDimension = s.getDimension(retailParameters.IS_ExcessAccount, retailPosBatchTable.StaffId);
                       JournalTrans.OffsetLedgerDimension = s.getDimension(retailParameters.IS_ExcessOffsetAccount, retailPosBatchTable.StaffId);
                       JournalTrans.AmountCurDebit = abs(retailPosBatchTable.overAmountTotal());
                       JournalTrans.AmountCurCredit = 0;
                   }
                   else
                   {
                       var s = new IS_RetailStatementJournalShortage();
                       JournalTrans.LedgerDimension = s.getDimension(retailParameters.IS_ShortageAccount, retailPosBatchTable.StaffId);
                       JournalTrans.OffsetLedgerDimension = s.getDimension(retailParameters.IS_OffsetShortageAccount, retailPosBatchTable.StaffId);
                       JournalTrans.AmountCurDebit = 0;
                       JournalTrans.AmountCurCredit = abs(retailPosBatchTable.overAmountTotal());
                   }
                   journalTrans.journalNum = JournalTable.JournalNum;
                   journalTrans.Txt = strFmt("%1 - %2",retailPosBatchTable.terminalID,retailPosBatchTable.batchid);
                   JournalTrans.AccountType            = LedgerJournalACType::Ledger;
                   JournalTrans.OffsetAccountType            = LedgerJournalACType::Ledger;
                   JournalTrans.TransDate              = retailPosBatchTable.CloseDate;
                   numberSeq = NumberSeq::newGetVoucherFromId(JournalTable.NumberSequenceTable, false);
                   voucher   = numberSeq.voucher();
                   JournalTrans.Voucher      = voucher;
                   JournalTrans.LineNum      = LedgerJournalTrans::lastLineNum(JournalTable.JournalNum)   1;
                   JournalTrans.CurrencyCode = Ledger::accountingCurrency(CompanyInfo::current());
                   JournalTrans.ExchRate = 100;
                   journalTrans.insert();
                   counter  ;
                   retailPosBatchTable.IS_Shortage = NoYes::Yes;
                   retailPosBatchTable.update();
               }// end if shift is posted
           }// end while shifts
           if(counter == 0)
           {
               ttsabort;
               Info("No shifts shortage/excess transactions were created.");
           }
           else
           {
               //ledgerJournalCheckPost = ledgerJournalCheckPost::newLedgerJournalTable(journalTable,NoYes::Yes);
               //ledgerJournalCheckPost.run();
               ttscommit;
               Info(strFmt("%1 Shifts shortage/excess transactions have been created.",counter));
           }    
       }
    public RecId getDimension(str _ledgerAccount, str _worker)
    {
       DimensionServiceProvider      DimensionServiceProvider = new DimensionServiceProvider();
       LedgerAccountContract        LedgerAccountContract = new LedgerAccountContract();
       DimensionAttributeValueContract   ValueContract;
       List                ListValueContract = new List(Types::Class);
       dimensionAttributeValueCombination dimensionAttributeValueCombination;
       DimensionStorage          dimStorage;
       if (_worker)
       {
           ValueContract = new DimensionAttributeValueContract();
           ValueContract.parmName('Worker') ;
           ValueContract.parmValue(_worker);
           ListValueContract.addEnd(ValueContract);
       }
       LedgerAccountContract.parmMainAccount(_ledgerAccount);
       LedgerAccountContract.parmValues(ListValueContract);
       dimStorage = DimensionServiceProvider::buildDimensionStorageForLedgerAccount(LedgerAccountContract);
       dimensionAttributeValueCombination = DimensionAttributeValueCombination::find(dimStorage.save());
       return dimensionAttributeValueCombination.RecId;
    }
       boolean canGoBatchJournal()
       {
           return true;
       }
       public container pack()
       {
           return conNull();
       }
       //Returns the stored object for the batch to use
       public boolean unpack(container packedClass)
       {
           return true;
       }
       //Determines whether to run on server or client
    //True - Server; False - Client
       public boolean runsImpersonated()
       {
           return true;
       }
    }

  • nmaenpaa Profile Picture
    101,158 Moderator on at
    RE: Create batch job through X++ code

    I'm sorry but we can't troubleshoot your code if you don't share it and instead share some "just an example" that doesn't contain all the details.

    Please share your full class. For example, we still can't see what's in your main method so it's just not possible for us to see what could be wrong.

  • sylvesterPowerBi Profile Picture
    384 on at
    RE: Create batch job through X++ code

    Dear Nikolaos,

    This code is just an example, the below code is the one im trying to generate:

    public class IS_RetailStatementJournalShortage extends RunBaseBatch

    {        

               /// <summary>

       /// Runs the class with the specified arguments.

       /// </summary>

       /// <param name = "_args">The specified arguments.</param>

       public static void main(Args _args)

       {  

    //my code

       }

       boolean canGoBatchJournal()

       {

           return true;

       }

       public container pack()

       {

           return conNull();

       }

       //Returns the stored object for the batch to use

       public boolean unpack(container packedClass)

       {

           return true;

       }

       //Determines whether to run on server or client

    //True - Server; False - Client

       public boolean runsImpersonated()

       {

           return true;

       }

    }

    What i want to know is, is there any missing method that keeping my code not running ?

    Regards,

  • Martin Dráb Profile Picture
    233,011 Most Valuable Professional on at
    RE: Create batch job through X++ code

    main() and run() do completely different things; you can't use one instead of the other.

    • run() is what will execute when the batch is actually triggered.
    • main() is called when you have a menu item for the class. All it typically does it creating an instance, calling prompt() (to display a dialog) and run().

    Your run() method won't do anything, because it doesn't contain any runnable code. The call of info() is commented out.

    Also, it's not clear whether you know how to see the result. You would find Infolog messages in batch history ("Log" button).

  • Suggested answer
    nmaenpaa Profile Picture
    101,158 Moderator on at
    RE: Create batch job through X++ code

    How did you set the batch to run? I don't see any main method in your class. Normally there would be a main method in RunBaseBatch based batches. That's executed when you launch the class from menu (menu item), and it contains the logic for showing the batch setup dialog (calling prompt method) and running the actual logic (run method).

    Check Tutorial_RunbaseBatch class in AOT.

  • Suggested answer
    Sukrut Parab Profile Picture
    71,682 Moderator on at
    RE: Create batch job through X++ code

    You can create batch in two ways by extending RunbaseBatch or using Sysoperation framework. You are doing using RunbaseBatch. You can refer standard doc and figure out  what you are doing wrong 

    https://docs.microsoft.com/en-us/dynamicsax-2012/developer/walkthrough-extending-runbasebatch-class-to-create-and-run-a-batch

    If  you want to learn about how to create batch using Sysoperation framework refer below links.

    https://community.dynamics.com/365/financeandoperations/b/dynamicsaxinsightbyanas/posts/ax-2012-create-a-simple-batch-job

    daxmusings.codecrib.com/.../from-runbase-to-sysoperation-business.html

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

🌸 Community Spring Festival 2025 Challenge 🌸

WIN Power Platform Community Conference 2025 tickets!

Jonas ”Jones” Melgaard – Community Spotlight

We are honored to recognize Jonas "Jones" Melgaard as our April 2025…

Kudos to the March Top 10 Community Stars!

Thanks for all your good work in the Community!

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 294,261 Super User 2025 Season 1

#2
Martin Dráb Profile Picture

Martin Dráb 233,011 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,158 Moderator

Leaderboard

Product updates

Dynamics 365 release plans