Purchase Order Confirmation

 



Introduction

In Microsoft Dynamics 365 Finance & Operations (D365 F&O), Purchase Orders can be confirmed programmatically using the standard PurchFormLetter framework.

This approach is useful for:

  • Custom business processes
  • Batch jobs
  • Integrations
  • Custom forms
  • Automated procurement processes

Using the standard framework is recommended instead of directly updating the Purchase Order status because the framework executes the required standard business logic and validations.

Requirement

The requirement is to provide a reusable X++ method that can receive a PurchTable record and confirm the Purchase Order programmatically.

The solution should:

  1. Validate the Purchase Order.
  2. Create the required parameter records.
  3. Execute the standard Purchase Order confirmation framework.
  4. Handle the operation within a transaction.
  5. Return the Purchase Order after successful processing.

Solution

The standard PurchFormLetter framework can be used for Purchase Order confirmation.

The high-level flow is:

PurchTable
    |
    v
Create PurchFormletterParmData
    |
    v
Create PurchParmUpdate
    |
    v
Populate PurchParmTable
    |
    v
Create PurchFormLetter
    |
    v
Run Confirmation
    |
    v
Purchase Order Confirmed


X++ Implementation




public static PurchTable confirmPurchaseOrder(PurchTable _purchTable)
{
    PurchFormLetter          purchFormLetter;
    PurchFormletterParmData  purchFormLetterParmData;
    PurchParmUpdate          purchParmUpdate;
    PurchParmTable           purchParmTable;

    ttsBegin;

    // Create parameter data
    purchFormLetterParmData = PurchFormletterParmData::newData(
        DocumentStatus::PurchaseOrder,
        VersioningUpdateType::Initial);

    purchFormLetterParmData.parmOnlyCreateParmUpdate(true);
    purchFormLetterParmData.createData(false);

    purchParmUpdate = purchFormLetterParmData.parmParmUpdate();

    // Populate parameter table
    purchParmTable.clear();

    purchParmTable.TransDate =
        DateTimeUtil::getSystemDate(
            DateTimeUtil::getUserPreferredTimeZone());

    purchParmTable.DocumentDate =
        DateTimeUtil::getSystemDate(
            DateTimeUtil::getUserPreferredTimeZone());

    purchParmTable.Ordering = DocumentStatus::PurchaseOrder;
    purchParmTable.ParmJobStatus = ParmJobStatus::Waiting;
    purchParmTable.PurchId = _purchTable.PurchId;
    purchParmTable.PurchName = _purchTable.PurchName;
    purchParmTable.DeliveryName = _purchTable.DeliveryName;
    purchParmTable.DeliveryPostalAddress =
        _purchTable.DeliveryPostalAddress;
    purchParmTable.OrderAccount = _purchTable.OrderAccount;
    purchParmTable.CurrencyCode = _purchTable.CurrencyCode;
    purchParmTable.InvoiceAccount = _purchTable.InvoiceAccount;
    purchParmTable.ParmId = purchParmUpdate.ParmId;

    purchParmTable.insert();

    // Create Purchase Order confirmation
    purchFormLetter = PurchFormLetter::construct(
        DocumentStatus::PurchaseOrder);

    purchFormLetter.transDate(
        DateTimeUtil::getSystemDate(
            DateTimeUtil::getUserPreferredTimeZone()));

    purchFormLetter.proforma(false);
    purchFormLetter.specQty(PurchUpdate::All);
    purchFormLetter.purchTable(_purchTable);

    purchFormLetter.parmParmTableNum(purchParmTable.ParmId);
    purchFormLetter.parmId(purchParmTable.ParmId);
    purchFormLetter.purchParmUpdate(
        purchFormLetterParmData.parmParmUpdate());

    // Execute confirmation
    purchFormLetter.run();

    ttsCommit;

    return _purchTable;
}

How It Works

Create Parameter Data

PurchFormletterParmData prepares the parameter framework required for Purchase Order confirmation.

PurchFormletterParmData::newData(
    DocumentStatus::PurchaseOrder,
    VersioningUpdateType::Initial);

Create PurchParmTable

The Purchase Order information is copied into PurchParmTable, which associates the confirmation request with the Purchase Order.

Create PurchFormLetter

PurchFormLetter::construct() creates the standard framework responsible for processing the confirmation.

Execute Confirmation

Finally:

purchFormLetter.run();

executes the standard Purchase Order confirmation process.

Important Considerations

Before calling the method, the implementation should validate:

  • Purchase Order exists.
  • Purchase Order is in a valid status for confirmation.
  • Purchase Order belongs to the correct legal entity.
  • Required vendor and Purchase Order information is available.
  • The Purchase Order is not already being processed by another process.

For batch and integration scenarios, logging and retry handling should also be considered.


Risks

RiskMitigation
PO already confirmedValidate status before processing
Duplicate integration requestImplement idempotency
Concurrent confirmationUse appropriate locking/status validation
Confirmation failureAllow standard framework errors to propagate/log them
Transaction rollbackClearly define transaction ownership
Custom/ISV extensionsPerform regression testing


Recommended Approach

The recommended design is to keep the confirmation logic in a reusable service/class and allow different processes to call it:

                  +----------------+
                  | Batch / API /  |
                  | Custom Form    |
                  +-------+--------+
                          |
                          v
              +-----------------------+
              | PO Confirmation       |
              | Service               |
              +-----------+-----------+
                          |
                          v
              +-----------------------+
              | PurchFormLetter       |
              | Standard Framework    |
              +-----------+-----------+
                          |
                          v
              +-----------------------+
              | Confirm Purchase      |
              | Order                 |
              +-----------------------+

This avoids duplicating confirmation logic across different customizations.


Conclusion

PurchFormLetter is the preferred standard framework for programmatically confirming Purchase Orders in D365 F&O.

The key recommendation is to use the standard framework rather than directly updating Purchase Order status fields. This helps ensure that standard business logic and validations are executed correctly.

For production implementations, additional consideration should be given to validation, transactions, concurrency, idempotency, logging, and integration retry handling.

Support Faryal's Cusine


Virtual Fields Vs Computed Fields


 


Virtual Field:

A virtual field in D365FO is a field that doesn't have a direct representation in the database. It's a field that you can define in a table as if it were a regular data field, but its value is computed on-the-fly based on certain calculations or business logic whenever it is queried. Virtual fields are often used to display derived or computed information without storing it in the database.


Advantages of Virtual Fields:


  • No need to store redundant data in the database.
  • Useful for displaying calculated values without performing calculations every time.

Computed Field:

A computed field in D365FO is similar to a virtual field in that its value is calculated based on certain rules or business logic. However, computed fields are typically defined in the Application Object Tree (AOT) and are often used within forms or reports to display dynamic information based on specific calculations.


Advantages of Computed Fields:

  • Provides dynamic and real-time calculations.
  • Can be used for various display purposes within forms and reports.

In summary, both virtual fields and computed fields are used to display calculated or derived information in Dynamics 365 Finance and Operations. Virtual fields are defined in tables and calculated on-the-fly during queries, while computed fields are often used within forms and reports to display dynamic calculations based on business logic. The choice between them depends on where and how you want to display the calculated information.



Support Faryal's Cusine


Purchase Order Confirmation

  Introduction In Microsoft Dynamics 365 Finance & Operations (D365 F&O), Purchase Orders can be confirmed programmatically using th...