Invoicing

The last issue on our to-do list is the invoicing process. For this, we use a part of the standard application.

As explained in Chapter 1, Introduction to Microsoft Dynamics NAV, invoicing is done using a document structure with a header and a line table. This has a posting routine that will start the journal transactions.

For our application, we need to create the invoice document and make sure that when posted, it updates our sub administration.

The sales invoice documents in Microsoft Dynamics NAV are stored in the Sales Header (36) and Sales Line (37) tables. We will create a report that will combine the outstanding reservation entries into invoices allowing the user to filter on a specific entry or any other field value in the squash ledger entry table.

Reports in Microsoft Dynamics NAV are not just for printing documents; we can also use its dataset capabilities to start batch jobs.

To enable this, our batch job needs to have a special property, ProcessingOnly, so let's start a blank report and do this.

Invoice document

The report will browse through the squash ledger entries filtered on entry type Reservation and open Yes. The sorting is Open, Entry Type, Bill-to Customer No., and Reservation Date. To use sorting, the fields must be defined together as a key in the table definition.

Invoice document

As Bill-to Customer No. is the first non-filtered value in the sorting, we can assume that if this value changes, we need a new sales header.

For every squash ledger entry, we will generate a sales line as follows:

Now, our Sales Invoice is ready so we can start making the necessary changes to the posting process. Posting a sales document is done using a single posting codeunit and some helper objects.

So we will make a change to Codeunit 80. This codeunit has a specific structure that we need to understand before we go in and make the change.

The codeunit also has the Test Near, Test Far, Do it, and Clean up strategy so the first step is to make sure everything is in place before the actual posting starts. Let's have a look at how this codeunit is structured.

This first part does the test near step and a part of the test far step. The Ship, Invoice, and Receive fields are set in codeunit 81 and 82 but checked and completed to make sure.

The next step is moving the sales header information to the history tables for shipment, invoice, credit memo, or return receipt header. These sections are commented like this:

When this is done, the sales lines are processed. They are also moved to the various posted line tables. This is all part of the Do it section of the posting routine.

If there is a drop shipment in a purchase order, this is handled here. We will discuss drop shipments in Chapter 6, Trade.

  // Post drop shipment of purchase order
  PurchSetup.GET;
  IF DropShipPostBuffer.FIND('-') THEN
    REPEAT
      PurchOrderHeader.GET(
        PurchOrderHeader."Document Type"::Order,
        DropShipPostBuffer."Order No.");

Then there is a section that creates the financial information in the general journal. We will go deeper into this section in Chapter 3, Financial Management.

  IF Invoice THEN BEGIN
    // Post sales and VAT to G/L entries from posting buffer
    LineCount := 0;
    IF InvPostingBuffer[1].FIND('+') THEN
      REPEAT
        LineCount := LineCount + 1;
        Window.UPDATE(3,LineCount);

        GenJnlLine.INIT;
        GenJnlLine."Posting Date" := "Posting Date";
        GenJnlLine."Document Date" := "Document Date";

Then the Clean up section starts by calculating remaining quantities, VAT, and deleting the sales header and sales lines if possible.

IF ("Document Type" IN ["Document Type"::Order,
  "Document Type"::"Return Order"]) AND
   (NOT EverythingInvoiced)
THEN BEGIN
  MODIFY;
  // Insert T336 records
  InsertTrackingSpecification;

  IF SalesLine.FINDSET THEN
    REPEAT
      IF SalesLine.Quantity <> 0 THEN BEGIN
        IF Ship THEN BEGIN
          SalesLine."Quantity Shipped" :=
            SalesLine."Quantity Shipped" +
            SalesLine."Qty. to Ship";
          SalesLine."Qty. Shipped (Base)" :=
            SalesLine."Qty. Shipped (Base)" +
            SalesLine."Qty. to Ship (Base)";
        END;

The Clean up section ends by deleting the sales document and related information and clearing the variables used.

The change we are going to make is in the section where the lines are handled:

We will create a new function, PostSquashJnlLn. This way we minimize the impact on standard code and when we upgrade to a newer version, we can easily copy and paste our function and only need to change the calling place if required.

Our new function first gets the squash ledger entry it applies to and tests if it's still open and the bill-to customer no. has not changed. Then, we populate the squash journal line with the help of the sales line and the old squash ledger entry. Then dimensions are handled and the squash journal line is posted.

Now when we post an invoice, we can see that the invoice entries are created:

Making the change