web
You’re offline. This is a read only version of the page.
close
Skip to main content

Announcements

News and Announcements icon
Community site session details

Community site session details

Session Id :

Purchase Order Confirmation

Sheikh Sohail Profile Picture Sheikh Sohail 6,125

 



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.


This was originally posted here.

Comments

*This post is locked for comments