Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Finance | Project Operations, Human Resources, ...
Suggested answer

ProjFormLetter_Invoice_Extension

(0) ShareShare
ReportReport
Posted on by 12

I am newbie in D365 development, but has experience in Ax2012 development, My problem is the "new way of thinking" in D365.

I have an extension on projFormLetter_invoice and I need to do something with ProjInvoiceJour, when the invoice is posted.

I am posting two og more proposals at the same time so I need all the projInvoiceJour records.

I have created a COC on run() like this, but my code (this.doSomething(invoiceJour)) does only run on projInvoiceJour for the last projProposalJour that I have selected to post. Because of the code projProposalJour = this.parmProjProposalJour().

How can i get all projProposalJour records or all projInvoiceJour records?

public void run()
{
    ProjProposalJour projProposalJour;
    ProjInvoiceJour  invoiceJour;
    ;

    next run();
    projProposalJour = this.parmProjProposalJour();
    
    while select invoiceJour
    where invoiceJour.ProposalId == projProposalJour.ProposalId
    {
        if(MyParameters::find().AutoSettlementOnCreditNote == NoYes::Yes
        && invoiceJour.isCreditNote_CZ() == true)
        {
            this.doSomething(invoiceJour);
        }
        
    }
}

  • Martin Dráb Profile Picture
    231,923 Most Valuable Professional on at
    RE: ProjFormLetter_Invoice_Extension

    Note that you could improve performance a lot.

    You shouldn't use nested while selects unless necessary. Using a join will ne much more efficient.

    You fetch all fields from parmTable, but you need only ProposalId (and you won't need any if you use a join).

    You can also change the query to find credit notes only, therefore you don't have to fetch normal invoices from database.

    And you fetch all the data for no reason if AutoSettlementOnCreditNote is No. You should check that at the beginning.

    public void run()
    {
    	next run();
    	
    	this.xyzAutoSettleCreditNotes();
    }
    
    private void xyzAutoSettleCreditNotes()
    {
    	if (MyParameters::find().AutoSettlementOnCreditNote)
    	{
    		ProjInvoiceJour         invoiceJour; 
    		ProjInvoiceParmTable	parmTable;
    	
    		while select invoiceJour
    			where invoiceJour.InvoiceAmount < 0 
    			exists join parmTable
    				where parmTable.ProposalId == invoiceJour.ProposalId
    				   && parmTable.ParmId == this.parmId()
    		{
    			this.doSomething(invoiceJour);
    		}
    	}
    }

  • hefug Profile Picture
    12 on at
    RE: ProjFormLetter_Invoice_Extension

    Thanks for helping me guys.

    I solved it like this using this.ParmId() and ProjInvoiceParmTable

    public void run()
        {
            ProjProposalJour        projProposalJour;
            ProjInvoiceJour         invoiceJour; 
            ProjInvoiceParmTable    parmTable;
            ParmId                  parmId;
            ;
    
            next run();
            parmId = this.parmId();
    
            while select parmTable
                where parmTable.ParmId == parmId
            {            
                while select invoiceJour
                    where invoiceJour.ProposalId == parmTable.ProposalId
                {
                    if(MyParameters::find().AutoSettlementOnCreditNote == NoYes::Yes
                    && invoiceJour.isCreditNote_CZ() == true)
                    {
                        this.doSomething(invoiceJour);
                    }
                }
            }
        }

  • Martin Dráb Profile Picture
    231,923 Most Valuable Professional on at
    RE: ProjFormLetter_Invoice_Extension

    Sorry, I didn't realize that the output contract in ProjFormLetter isn't put to formletterOutputContract (as it is in PurchFormLetter, for example).

    I would get it from in formletterService.getOutputContract() in readFormletterServiceOutputs():

    [ExtensionOf(classStr(ProjFormLetter_Invoice))]
    class MyProjFormLetter_Invoice_Extension
    {
    	Set outJournalsAll;
    
    	protected void readFormletterServiceOutputs(FormletterService formletterService)
    	{
    		next readFormletterServiceOutputs(formletterService);
    		
            outJournalsAll = Set::create(formletterService.getOutputContract().parmAllJournalsPacked());
    	}
    	
    	public void run()
    	{
    		next run();
    		
    		if (outJournalsAll && !outJournalsAll.empty())
    		{
    			...
    		}
    	}	
    }

  • nmaenpaa Profile Picture
    101,156 Moderator on at
    RE: ProjFormLetter_Invoice_Extension

    Have you initialized a variable called formLetterOutputContract, or does it exist in the scope of the standard class? 

  • hefug Profile Picture
    12 on at
    RE: ProjFormLetter_Invoice_Extension

    Any ideas where to put the code (set::create(formletterOutputContract.parmAllJournalsPacked()))?

    I tired to put it in run(), after next run(); 

    I am getting the error: The qualifier 'FormLetterOutputContract' is not valid in this context. Use a variable of this tye instead.

  • Suggested answer
    nmaenpaa Profile Picture
    101,156 Moderator on at
    RE: ProjFormLetter_Invoice_Extension

    Hi,

    I'm not sure if D365 has any impact on this solution. If you need all selected ProjPropsalJours, you need to find a place in the code where all the selected ProjProposalJours are available. Do you already have an idea how you would implement your code in AX2012? If yes, could you please share it, so we can suggest how to do it in D365.

    I'm not so familiar with project invoice proposals. But if each proposal ends up as a separate invoice, then your current code would eventually call the "doSomething" for all created invoices. No matter if you selected 1 or 20 proposals, the ProjFormLetter_Invoice class would run once for each invoice, therefore also your "doSomething" method would run once for each created invoice. But like I said, I'm not sure if it really works like this.

    Also, please remember that you should use your prefix in the extension class naming. Instead of ProjFormLetter_Invoice_Extension, you should call it MYProjFormLetter_Invoice_Extension, where "MY" is your prefix.

  • Martin Dráb Profile Picture
    231,923 Most Valuable Professional on at
    RE: ProjFormLetter_Invoice_Extension

    Couldn't you get them from formletterOutputContract?

    Set journals = Set::create(formletterOutputContract.parmAllJournalsPacked());

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

Daivat Vartak – Community Spotlight

We are honored to recognize Daivat Vartak as our March 2025 Community…

Announcing Our 2025 Season 1 Super Users!

A new season of Super Users has arrived, and we are so grateful for the daily…

Kudos to the February 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... 293,238 Super User 2025 Season 1

#2
Martin Dráb Profile Picture

Martin Dráb 231,923 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,156 Moderator

Leaderboard

Product updates

Dynamics 365 release plans