Custom Purchase order Report assignment:
Functional Members and Devs. Developers, you will create a report using the
DP/Contract/Controller report which is a custom layout for Purchase orders. Functional
members, it will be your responsibility to explain the dev assignment and test it for accuracy
with your Devs. You do not need to sit with your dev for 2 days, but you do need to make sure
that he understands his work and that he gets it done. This must be done by 09/04/2025.
1) Purpose & scope
Goal: Produce a printable Purchase Order (PO) report matching the attached layout
(single-page summary with header, vendor block, ship-to block, shipping
terms/method/delivery date band, line grid, and footer totals with special instructions).
Systems: Dynamics 365 Finance & Supply Chain (D365FO).
Technology: SSRS precision design report integrated with Print management for
Purchase orders.
Audience: External suppliers (vendor-facing) and internal buyers.
Output: PDF/print/Email body (standard D365 print destinations supported).
2) Run locations & security
Entry points:
o Purchase order header (Procurement and sourcing > Purchase orders > All
purchase orders).
o Print management (Procurement and sourcing > Setup > Forms > Form setup
and Print management).
Menu item security: same as standard PO confirmation/report. Grant to roles:
Purchasing agent, Purchasing manager, Accounts payable manager. (No additional
privileges beyond reading PO data.)
3) Parameters (Dialog)
Parameter Type Default Notes
Current PO (if
Purchase order PurchId (lookup) Required
launched from form)
Enum For watermark & “PO #”
Copy/Original Original
(Original/Copy) sequencing if desired
Language LanguageId From vendor Overrides report language
For scenarios where price
Include prices Yes/No Yes
hiding is needed
Show line with zero Filters lines with zero
Yes/No No
amount qty/amount
If No, show single Tax line
Show tax breakdown Yes/No Yes
in footer
Show company logo Yes/No Yes Logo from CompanyInfo
Override ‘Special If populated, replaces header
Free text Blank
instructions’ field (see §6)
Shipping charge List of “FREIGHT”, “SHIP”, Used to sum shipping in
Parameter Type Default Notes
code(s) MarkupCode “SHIPPING” footer (see §7)
4) Data model (RDP or Query)
Recommendation: Use DP (Data Provider) class with one temp table for header and one for
lines, because we need calculated totals and flexible charge/tax aggregation.
4.1 Tables & joins (read-only)
PurchTable (header) – PurchId, VendAccount, OrderAccount, DocumentDate,
CurrencyCode, DlvMode, DlvTerm, DeliveryName, InvoiceAccount, PurchName,
DiscPercent, DiscAmount, PurchStatus.
PurchLine (lines) – PurchId, LineNum, ItemId (not always used), Name (description),
QtyOrdered/PurchQty, PurchPrice, LineAmount (amount including line discounts),
DeliveryDate, PurchUnit.
VendTable (vendor) via [Link].
CompanyInfo (logo, company name, phone, email, website).
DirPartyTable / DirPartyLocation / LogisticsPostalAddress /
LogisticsElectronicAddress for vendor and company addresses, phone, email, website.
LogisticsPostalAddress for Ship-to (from [Link] via
RecId relation).
TaxTrans / TaxTransGeneralJournal (or TaxCalculation framework service) to
compute tax per PO when available; else compute via totals on PurchTotals.
MarkupTrans (charges) filtered for MarkupModule = Purch and TransTableId =
tableNum(PurchTable)/PurchLine, to calculate Shipping (sum of specified codes).
PurchTotals class (framework) to compute header totals reliably (currency conversion,
discounts, etc.).
Developer note: follow standard patterns used by
[Link]/PurchPurchaseOrderDP. We’re not replacing the standard form;
we’re delivering a branded variant with the layout below.
5) Dataset schema (temp tables)
5.1 Header temp table (Example: DT_PORptTmpHeader)
Field (EDT) Source/Calc Notes / Mapping to layout
PurchId (PurchId) [Link] Printed as PO #
[Link] (fallback:
PODate (TransDate) Printed as Date top right
CreatedDateTime date)
CompanyName
[Link] Top-left block
(Name)
Field (EDT) Source/Calc Notes / Mapping to layout
CompanyAddr Company postal address (company’s
Multi-line
(LongAddress) postal)
CompanyPhone
LogisticsElectronicAddress Optional
(Phone)
CompanyEmail
LogisticsElectronicAddress Optional
(Email)
CompanyWebsite
LogisticsElectronicAddress Optional
(URL)
VendorName (Name) VendTable / [Link] “Vendor” block
VendorContact [Link] / primary
“Contact or Department”
(Name) contact
VendorAddress
Vendor primary postal address Multi-line
(LongAddress)
VendorPhone (Phone) Electronic address
VendorEmail (Email) Electronic address
[Link] (fallback
ShipToName (Name) “Ship To” block line 1
Site/Warehouse name)
ShipToCompany [Link] or Ship-to company
(Name) if different
ShipToAddress
[Link] Multi-line
(LongAddress)
ShipToPhone (Phone) Optional from delivery contact
ShipToEmail (Email) Optional from delivery contact
ShippingTerms
(DlvTermId / [Link] Printed in top band
description)
ShippingMethod
(DlvModeId / [Link] Printed in top band
description)
DeliveryDate If header-level delivery date present else
Printed in top band
(TransDate) Earliest [Link]
Currency
[Link] For money formatting
(CurrencyCode)
Subtotal Sum of line LineAmount (excl. header
Footer “SUBTOTAL”
(AmountCur) charges, taxes)
Derived: if parameter “Show tax
TaxPercent Footer label “TAX RATE”
breakdown” off, show header effective
(AmountPercent) shows percent
rate; else blank
TaxAmount Footer “TAX” (if we show
Sum of tax for document
(AmountCur) explicit amount)
Footer “DISCOUNT” percent;
DiscountPercent
[Link] (header) if amount only exists, compute
(AmountPercent)
pct = DiscAmount/Subtotal
Field (EDT) Source/Calc Notes / Mapping to layout
Footer “DISCOUNT” amount
DiscountAmount [Link] +
(we’ll display as percent or
(AmountCur) sum([Link])
amount per design)
∈ parameter list
ShippingAmount Sum MarkupTrans where MarkupCode
Footer “SHIPPING”
(AmountCur)
GrandTotal Subtotal - DiscountAmount +
TaxAmount + ShippingAmount Footer “TOTAL”
(AmountCur)
SpecialInstructions New custom field on PurchTable (see Printed in “SPECIAL
(Notes) §6) or parameter override INSTRUCTIONS” section
IsCopy (NoYesId) Parameter Used for watermark
5.2 Line temp table (Example: DT_PORptTmpLine)
Field (EDT) Source Notes / Mapping
PurchId (PurchId) [Link] FK to header temp
LineNum (LineNum) [Link] Hidden; for sorting
Layout shows ITEM # (“00001”). Use
ItemNumber (ItemId /
If ItemId exists else blank formatted LineNum (5 digits) when no
String)
ItemId
Description (ItemName
[Link] DESCRIPTION column
/ Name)
[Link]
Qty (Qty) QTY
(ordered)
UnitPrice
[Link] UNIT PRICE
(AmountCur)
LineTotal
[Link] TOTAL (after line discounts, before tax)
(AmountCur)
LineDeliveryDate
[Link] For potential tooltip/export if needed
(TransDate)
PurchUnit (UnitId) [Link] Optional display
Filters: Exclude canceled lines; apply parameter “Show line with zero amount”.
6) Customization: Special Instructions
(header)
The sample shows a long paragraph under “SPECIAL INSTRUCTIONS”. Standard PO has
limited free-text. We require a new extension field:
Table/Field: PurchTable.DT_SpecialInstructions (EDT DT_SpecialInstructions,
String 2000).
UI: Add to “Purchase order” header (tab: General > Administration fast tab, or Notes fast
tab).
Report behavior: If parameter “Override ‘Special instructions’” has a value, the report
uses it; otherwise print PurchTable.DT_SpecialInstructions. If both empty, hide the
block.
7) Calculations & business rules
1. Subtotal = Σ LineTotal (from [Link] for included lines).
2. Discount:
o Prefer [Link] (header).
o Add Σ line discounts if not already netted into LineAmount (developer to use
PurchTotals to avoid double-count).
o Show either [Link]% or $x,[Link] as per available values. If both, show percent
and compute amount for total.
MarkupCode ∈ parameter codes. If none, 0.00.
3. Shipping = Σ MarkupTrans where TransTableId relates to the PO header or lines AND
4. Tax = Use framework (PurchTotals::construct(PurchTable).taxAmount()) or sum
of [Link] for the PO.
o Tax Rate: if requested, compute effective TaxAmount / (Subtotal -
DiscountAmount) and format as percent (2 decimals).
5. Grand Total = Subtotal - DiscountAmount + ShippingAmount + TaxAmount.
6. Currency = [Link]. Apply currency rounding from
Currency::round.
7. Shipping method/terms: print descriptions (from DlvMode and DlvTerm tables), not
IDs.
8. PO Date: use [Link] if present; fallback to
[Link] (date part).
9. Addresses:
o Format as multi-line postal addresses via LogisticsAddressFormatter.
o Vendor “Contact or Department” = vendor primary contact person (if missing,
leave blank).
o Ship-to Company = [Link] unless a separate delivery company is
specified.
10. Item #: display [Link]; if blank (service line), display zero-padded LineNum
(00001, 00002, …) to match the sample.
11. Hidden zeros: In the totals list (middle column in sample shows many $0.00 rows), we
will not render intermediate zero rows; we will only render the four shown rows
(Subtotal, Tax, Discount, Shipping) and Total. (This keeps the report clean.)
8) Layout & branding (SSRS precision
design)
Header bar: Page title “PURCHASE ORDER” top-right; Company logo top-left
([Link]).
Left column: Company block with address, phone, email, website.
Right column: Two header fields: Date and PO #.
Two panels:
o Vendor panel (purple header in sample).
o Ship To panel (same style).
Shipping band: 3 equal cells: Shipping Terms, Shipping Method, Delivery Date.
Line grid: columns Item #, Description, Qty, Unit price, Total.
Footer: Left – “SPECIAL INSTRUCTIONS” paragraph; Right – totals table:
SUBTOTAL, TAX RATE (or “TAX”), DISCOUNT, SHIPPING, TOTAL (bold
highlight).
Fonts & colors: Use theme variables; provide parameters or constants to match the
sample (e.g., Dark Blue #0D1A26 for headings, Bright Blue #007BFF for accents) if
branding is required.
Pagination: Repeat column headers on each page; totals only on last page.
9) Localization & formatting
Date format: user’s language/culture (override from parameter).
Currency format: currency symbol and decimals per Currency setup.
Labels: support label files @DT: to allow translation.
10) Integration with Print management
Document type: Purchase order.
Replacement: This report is a new design DT_PurchaseOrder.Report wired to
Purchase order in Print management (can be company-specific).
Email template: Subject Purchase Order %PurchId%, body includes GrandTotal and
VendorName.
11) Developer deliverables
AOT objects:
o Report: DT_PurchaseOrder.Report (precision design),
DT_PurchaseOrder.Controller, DT_PurchaseOrder.Contract,
DT_PurchaseOrder.DP.
o Temp tables: DT_PORptTmpHeader, DT_PORptTmpLine.
o EDTs/Labels for any new fields (e.g., DT_SpecialInstructions).
o Table extension: PurchTable.DT_SpecialInstructions.
o UI extension for PurchTable form to expose the new field.
Business logic:
o Use PurchTotals to compute amounts; avoid duplicated discount/tax math.
o Address formatting via Logistics address formatter classes.
o Retrieve electronic addresses for phone/email/URL.
o MarkupTrans filter by parameter codes.
o Respect “Include prices” parameter (if No, hide Unit price/Total columns and all
monetary totals except possibly Qty).
12) Test scenarios & acceptance criteria
12.1 Scenarios
1. Standard PO with stock items (multiple lines, tax, freight, header discount).
o Verify all blocks populate; totals equal PurchTotals.
2. Service-only PO (no ItemId) – Item # shows padded LineNum.
3. Zero-amount line – excluded when parameter is No.
4. No tax / no freight – those rows show “$0.00” or are hidden per spec (we’ll still show
the row with $0.00 for predictability unless requested otherwise).
5. Copy version – watermark “COPY”.
6. Language override – report renders labels and date format per parameter.
7. Special instructions – pulls from header field; parameter override works.
8. Multi-page – repeat table headers; totals on last page only.
12.2 Acceptance criteria
Values for Subtotal, Discount, Tax, Shipping, Total match PurchTotals and
MarkupTrans sums (±currency rounding).
Vendor/Ship-to addresses match those on the PO exactly (including country/region
formats).
PO prints from Print management with correct destination behavior.
Layout aligns with the provided sample (sections, labels, ordering, and highlight of
TOTAL).
13) Field dictionary (developer quick
reference)
Header
Date → [Link] (date)
PO # → [Link]
Company name/address/phone/email/website/logo → CompanyInfo +
LogisticsElectronicAddress + image from CompanyInfo
Vendor block
o Company → VendTable/[Link]
o Contact/Dept → Vendor primary contact (ContactPerson)
o Address → Vendor postal address (LogisticsPostalAddress via party)
o Phone/Email → Electronic addresses
Ship To block
o Name → [Link]
o Company → [Link]
o Address → [Link]
o Phone/Email → delivery contact if present
Shipping terms → [Link] for [Link]
Shipping method → [Link] for [Link]
Delivery date → Earliest [Link] (or header if present)
Special instructions → PurchTable.DT_SpecialInstructions (custom) or parameter
override
Lines
Item # → Prefer [Link]; else formatted [Link] (5 digits)
Description → [Link]
Qty → [Link]
Unit price → [Link]
Total → [Link] (post line discount, pre tax/charges)
Totals
Subtotal → Σ LineAmount
Tax rate → computed % (optional display)
Tax → [Link]() (or sum TaxTrans)
Discount → [Link] (+ any residual line discounts)
Shipping → Σ [Link] filtered by code list
Grand total → Subtotal − Discount + Shipping + Tax
[Skip Section 14 for now]
14) Performance & quality
Use set-based reads; single call to PurchTotals per header.
Cache address and contact lookups.
Support batch printing for multiple POs (Print management).
Unit tests for DP calculations where feasible.