Skip to main content

Scenario: Activate new standard costs

Goal. New standard costs reach D365 as pending prices of a costing version, either worked out by your costing or product lifecycle tool, or calculated by D365 from the items' BOMs and routes at your request. You then make them active from outside D365. Lattice runs the same calculation and activation as the D365 pages: the calculation records each item's rolled-up cost as a pending price, and the activation makes the pending prices the active prices, revalues the on-hand inventory of a standard cost item at its new cost, and posts the revaluation to the general ledger. The responses tell you which prices were calculated and activated, and in which voucher the revaluation was posted.

When to use. A standard cost roll at the start of a period or year, once the new costs are approved, or a single item whose standard cost has to change. Calculate and activate every item of the costing version at once, or only the items you name. To change stock quantities rather than costs, use Inventory journals.

Prerequisites​

  1. Security.

    • Calculating item costs records pending prices only: nothing is activated, revalued or posted. It needs privilege MGCLatticeInventoryCostCalculateMaintain ("Inventory cost - calculate item costs"), which is in duty MGCLatticeIntegrationServiceOperationsDuty of the integration operator and administrator roles.
    • Activating standard costs revalues inventory and posts to the general ledger, so the operation is high-risk. It needs privilege MGCLatticeInventoryCostActivateMaintain ("Inventory cost - activate pending prices (high-risk)"), which is in duty MGCLatticeIntegrationServiceHighRiskDuty of the integration administrator role only. The operator role, the calculation privilege and the inventory privilege MGCLatticeInventoryServiceMaintain do not grant it.

    Without the privilege D365 refuses the call with HTTP 403. See Security model.

  2. D365 setup in the legal entity.

    • A costing version for the prices (Cost management > Predetermined cost policies setup > Costing versions) that allows cost prices, with Blocked set to No to calculate and Block activation set to No to activate. USMF ships version 10 for standard costs (no site, fixed date 2018-01-01).
    • The pending prices, entered in that version: on the Pending prices tab of an item's Item price page (Product information management > Products > Released products, Manage costs > Item price), by a BOM calculation (step 1b below), or through the standard InventItemPendingPricesV2 entity (step 1a). A pending price is activated only when it is dated today or earlier. A costing version with a fixed From date needs its pending prices to carry that date: in USMF version 10 it is 2018-01-01.
    • To calculate an item's cost: an active, approved BOM and route at the site (USMF D0003 at site 1), and a number sequence for calculation numbers (BOM calculations).
    • For the revaluation of on-hand inventory: the items use a standard cost inventory model, their inventory posting profile has the standard cost accounts (Inventory management > Setup > Posting > Posting, Item tab), and the ledger period of today is open.
  3. Lattice. A valid license (a never-registered environment is allowed through; an adverse verdict refuses the call with LicenseNotValid). The request takes no external keys and needs no Lattice parameters.

Steps​

The operations are calculateItemCosts and activatePendingPrices on MGCLatticeInventoryCostService in service group MGCLatticeInventoryServiceGroup. Send a POST with an OAuth 2.0 bearer token and the request in _request (see Trial and day-one guide).

  1. Get the new costs into pending prices. Skip this step when your costs are already pending in D365. Otherwise either enter them (a) or have D365 calculate them (b).

    a. Enter the costs your tool worked out. Create one pending cost price per item and site in the costing version, dated the version's From date (or, when the version has none, today or earlier):

    POST https://<your-environment>/data/InventItemPendingPricesV2
    {
    "dataAreaId": "usmf",
    "ItemNumber": "M0001",
    "CostingVersionId": "10",
    "PriceType": "Cost",
    "FromDate": "2018-01-01T12:00:00Z",
    "Price": 3.95,
    "PriceQuantity": 1,
    "PriceSiteId": "1"
    }

    b. Have D365 calculate them with calculateItemCosts, as Costing versions > Calculation does: the standard item cost calculation rolls up each item's BOM and route costs (and, for an item procured by purchase when the version calculates those, its purchase price) and records the result as the item's pending cost price in the version, dated the calculation date.

    POST https://<your-environment>/api/services/MGCLatticeInventoryServiceGroup/MGCLatticeInventoryCostService/calculateItemCosts
    {
    "_request": {
    "RequestId": "7c4e2a90-3f1b-4d68-b5a2-9e0d1c8f6b43",
    "LegalEntityId": "USMF",
    "UserContext": "cost-roll",
    "CostingVersionId": "10",
    "SiteId": "1",
    "ItemIds": ["D0003"]
    }
    }
    • Site. A calculation runs for one site. Send SiteId when the version has no site; a version restricted to a site calculates for that site.
    • Date. CalculationDate is the calculation date and the from date of the pending prices. Leave it out to use the version's fixed date (2018-01-01 for USMF version 10) or, when it has none, today. A version with a fixed date accepts only that date.
    • Items. Leave out ItemIds to calculate every item of the legal entity, as the costing version's Calculation does; the run then succeeds when it recorded at least one pending price. With ItemIds, every named item must get a pending cost price.
    • The calculation uses the costing version's own settings (profit setting, fallback principle, cost price and purchase price models, rounding; single level for a standard costing version) and overwrites an existing pending price of the same item, site and date. Like the standard it calculates each item on its own: an item that fails does not stop the others.

    DocumentId is the costing version and PostedDocumentId the calculation number of the first calculated item, which the pending price refers to. The message counts the prices and names the items, for example Calculated 1 pending price(s) in costing version 10 for site 1 on <date>: D0003. The calculation's own warnings (no BOM, no route, zero cost price, fallback price used) are in Warnings. Review the pending prices before you activate them; to discard one, delete it on the Item price page.

  2. Activate the pending prices. Name the costing version and, to limit the run, the items:

    POST https://<your-environment>/api/services/MGCLatticeInventoryServiceGroup/MGCLatticeInventoryCostService/activatePendingPrices
    {
    "_request": {
    "RequestId": "2b7e4c19-5d3a-4f8e-9a61-0c4d2e8f1b37",
    "LegalEntityId": "USMF",
    "UserContext": "cost-roll",
    "CostingVersionId": "10",
    "ItemIds": ["M0001"]
    }
    }

    After step 1b, name the items you calculated (for example ["D0003"]) once their pending prices are reviewed. Leave out ItemIds to activate every eligible pending price of the version. A pending price is eligible when it is the newest one of its item, price type and price dimensions, is dated today or earlier, and passes the standard activation checks. All of them are activated in one transaction: if D365 refuses one, none is activated.

    • Price types. ActivateCostPrice, ActivatePurchasePrice and ActivateSalesPrice choose which pending prices are activated. With none of them, cost prices only are activated (the new standard costs).
    • Cost category prices. ActivateCostCategoryPrices true also activates the version's pending routing cost category prices and cost sheet calculation factors. They apply to the whole version, so send it without ItemIds.
    • Unchanged prices. SkipIfEqualPriceExists true leaves a pending price that equals the active price pending.
  3. Read the result. A successful activation answers Success true and Status 3. DocumentId is the costing version; PostedDocumentId is the voucher of the on-hand revaluation:

    OutcomePostedDocumentIdMessage
    Prices activated and on-hand inventory revaluedThe revaluation voucher"Activated 1 pending price(s) in costing version 10: M0001. On-hand inventory was revalued on voucher IAV-000041."
    Prices activated, no on-hand inventory to revalueEmpty"Activated N pending price(s) in costing version 10: ..."
    No item price activatedEmpty"No item price was activated in costing version 10: every eligible pending price equals the active price, or only cost category prices and calculation factors were pending."

    The last outcome is a success too: nothing needed to change. Use PostedDocumentId (not the message text, which is localized) to decide whether a revaluation was posted.

The bulk variants calculateItemCostsBatch and activatePendingPricesBatch take a _requests list, for example one item per legal entity or costing version, and answer one result per item. A large costing version can take longer than your HTTP client waits: queue calculateItemCosts or activatePendingPrices with submitAsyncOperation (ServiceName MGCLatticeInventoryCostService, OperationName the operation) and poll it with getAsyncOperationStatus. Both are described in Batch and async operations.

How to verify​

  • The calculation response: Success true, Status 3, DocumentId = the costing version, PostedDocumentId = a calculation number. The pending price is in the standard InventItemPendingPricesV2 entity (filter on ItemNumber, CostingVersionId and PriceSiteId), and in D365 on the Pending prices tab of Costing versions > Item price (or the item's Item price page), with the calculation number; the calculation's lines are under that calculation number.
  • The activation response: Success true, Status 3, DocumentId = the costing version and, when on-hand inventory was revalued, the voucher in PostedDocumentId.
  • The prices: the standard InventItemPendingPricesV2 entity no longer lists the activated prices, and InventItemPricesV3 returns the new active price, for example GET https://<your-environment>/data/InventItemPricesV3?cross-company=true&$filter=dataAreaId eq 'usmf' and ItemNumber eq 'M0001' and CostingVersionId eq '10' and PriceSiteId eq '1'.
  • The revaluation: LatticeGeneralLedgerEntries with $filter=SubledgerVoucher eq '<voucher>' and LegalEntityId eq 'USMF'.
  • In D365: on the item's Item price page (Released products, Manage costs > Item price) the price has moved from the Pending prices tab to the Active prices tab, with today as its activation date. The same tabs show the whole version from Costing versions > Item price. The revaluation voucher is on General ledger > Inquiries and reports > Voucher transactions.
  • The call: System administration > Inquiries > Lattice > Services > Service call log, or LatticeServiceCallLogs filtered on your RequestId.

When it goes wrong​

A failed call answers Success false, Status 4, an ErrorCode and a generic Message; the reasons are in Errors.

Calculation. Nothing is activated. Request checks fail before anything is calculated; an item that could not be calculated does not undo the prices recorded for the other items.

ErrorCodeTypical cause (text in Errors)What to do
ValidationFailed (1)No RequestId, unknown LegalEntityId, no CostingVersionId; "SiteId is required: costing version 10 is not restricted to a site, ..."; an unknown site or a site other than the version's; "Costing version 10 has the fixed calculation date ..., so CalculationDate ... cannot be used."; an unknown item in ItemIds; a version that does not allow cost prices, or a standard cost conversion versionCorrect the request and resend.
DocumentNotFound (2)"Costing version X was not found in legal entity Y."Send a costing version of that legal entity.
InvalidStatus (3)"Costing version X is blocked, so its item costs cannot be calculated." (Blocked, not Block activation)Unblock the version, then resend.
ConfigurationMissing (11)"The number sequence for calculation numbers (BOM calculations) is not set up in legal entity ..."Assign the number sequence, then resend.
BusinessRule (4)"The calculation in costing version ... recorded no pending price."; "No pending cost price was calculated in costing version ... for D0003. ... The N pending price(s) calculated for the other items stay recorded, and calling again recalculates them."Fix the BOM, route or cost setup named in Errors (no active BOM or route at the site, for example), then call again.
PreviewUnsupported (10)PreviewMode true: calculation has no previewSend without PreviewMode. Nothing was run.

Activation. Nothing is activated.

ErrorCodeTypical cause (text in Errors)What to do
ValidationFailed (1)No RequestId or unknown LegalEntityId; "CostingVersionId is required."; "Item 'X' was not found." for an item in ItemIds; "Cost category prices and calculation factors apply to the whole costing version: send ActivateCostCategoryPrices without ItemIds."Correct the request and resend.
DocumentNotFound (2)"Costing version X was not found in legal entity Y."Send a costing version of that legal entity.
InvalidStatus (3)"Costing version X is blocked for activation."Set Block activation to No on the costing version once the costs are approved, then resend.
BusinessRule (4)"Costing version X has no pending price dated ... or earlier for the requested price types and items." (nothing pending, a pending price dated in the future, or a price type you did not ask for); or the standard activation refused a priceEnter or correct the pending prices, or fix the setup named in Errors, then resend.
PreviewUnsupported (10)PreviewMode true: activation has no previewSend without PreviewMode. Nothing was run.
TransientRuntime (6)Infrastructure fault; IsRetryable trueResend with the same RequestId.
DuplicateRequest (7)The RequestId was first used for another operationSend a new RequestId.
LicenseNotValid (12)The license verdict is adverse; IsRetryable trueRenew the license, then resend.

TransientRuntime, DuplicateRequest and LicenseNotValid apply to the calculation the same way.

Choosing the RequestId. A calculation or an activation is a run, not a document: resending a RequestId that succeeded returns the first result and runs nothing again, while a new RequestId runs a new calculation or activation. Give each run (legal entity, costing version, cost roll) its own stable RequestId, and reuse it only when you retry that same run. A failed run releases its RequestId, so you can resend it after fixing the cause.

Queued runs. A run submitted with submitAsyncOperation that fails while it runs lands in the dead-letter queue (System administration > Inquiries > Lattice > Integration operations > Integration operations console); see Integration operations.

Reference​