Skip to content

[Backport 29.x] Bug 648535: Reprice subcontracting lines after scheduling (#10917) - #11197

Open
Chethan Thopaiah (ChethanT) wants to merge 6 commits into
releases/29.xfrom
private/ChethanT/backport-10917-29.x-20260908094110
Open

[Backport 29.x] Bug 648535: Reprice subcontracting lines after scheduling (#10917)#11197
Chethan Thopaiah (ChethanT) wants to merge 6 commits into
releases/29.xfrom
private/ChethanT/backport-10917-29.x-20260908094110

Conversation

@ChethanT

@ChethanT Chethan Thopaiah (ChethanT) commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Backport of #10917 to releases/29.x

Backports #10917Bug 648535: Reprice subcontracting lines after scheduling — to the releases/29.x release branch.

What & why

Subcontracting purchase lines were priced before backward scheduling had finalized the purchase-line Order Date and before routing context was transferred from the requisition line, so a subcontractor price valid for the purchase-header date could be selected instead of the price valid for the final purchase-line date.

The review follow-up also:

  • preserves the worksheet's calculated Units/Time cost when no subcontractor price matches;
  • preserves manually overridden worksheet costs during carry-out;
  • keeps date scheduling editable on released purchase orders without changing financial terms;
  • reprices lead-time-only changes when the resulting Order Date crosses a price boundary.

Source

Cherry-pick / conflict resolution

The product changes applied cleanly. The test file conflicted because the release branch predates the Subc. Management Library helper refactor. Only the relevant regression tests were applied, using equivalent local helper procedures already required by this backport. No unrelated main tests were introduced.

Validation

  • Static verification: no conflict markers or duplicate procedures; git diff --check passes.
  • Four corrective regressions cover no-price fallback, manual worksheet overrides, released-order date edits, and lead-time-only Order Date changes.
  • Full AL compile and test execution are deferred to the AL-Go PR build because local symbol packages are unavailable and sandbox policy blocks CoreXT package-state initialization.

⚠️ Do not merge until the AL-Go PR build passes. Not auto-merged.

[AB#648535](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/648535)

Subcontracting purchase lines were priced before backward scheduling had
finalized the purchase-line Order Date and before routing context was
transferred from the requisition line. This could select a subcontractor
price valid for the purchase-header date rather than the price valid for
the final purchase-line date.

This change reapplies subcontractor pricing after
requisition-to-purchase-line manufacturing fields are transferred. It
also reprices existing subcontracting lines after Planned Receipt Date
reschedules Order Date and after Order Date is validated directly. The
existing guarded price helper keeps ordinary purchase lines unchanged.

Internal ADO bug:
https://dev.azure.com/dynamicssmb2/Dynamics%20SMB/_workitems/edit/648535

- [x] I read the full diff and it contains only changes I intended.
- [ ] I built the affected app(s) locally with no new analyzer warnings.
- [ ] I ran the change in Business Central and confirmed it behaves as
expected.
- [x] I added or updated tests for the new behavior, or explained below
why none are needed.

**What I tested and the outcome** *(required - be specific: scenarios,
commands, screenshots for UI changes)*

- Added regression coverage proving initial purchase-order creation uses
the price valid on the final backward-scheduled Order Date.
- Added regression coverage proving Expected Receipt Date rescheduling
selects the price valid on the newly derived Order Date.
- Added regression coverage proving direct Order Date validation
reapplies date-effective pricing.
- Ran the BCQuality AL branch review at Medium severity: no findings.
- Local app build and Business Central execution are pending because
Docker Desktop's Windows engine returned HTTP 500 after its service was
started. The BCApps AL-Go PR build will provide build, analyzer, and
test execution results.

No schema, public API, permission, upgrade, or data-migration changes.
The new subscribers reuse existing price selection and feature-flag
guards. Non-subcontracting purchase lines remain excluded by the
existing item, production-order, and operation checks.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@attilatoury attilatoury left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical review

Reviewed commit 6a3802a0a30c9740cd015c7353c60c7fc62ddae9 against releases/29.x. Recommend addressing the following before merging; details and suggested regression coverage are in four inline comments:

  1. [P1] Carry-out replaces correctly calculated time/UOM-based costs with the raw routing rate when no subcontractor price matches.
  2. [P1] The new date handlers reject date changes on released subcontracting POs through discount validation's open-status check.
  3. [P2] Carry-out silently discards manually entered worksheet costs, including when no price-period change occurs.
  4. [P2] Lead-time-only rescheduling can still leave a stale price because the planned-date equality guard ignores a changed order date. This is an incomplete-fix case, not a new regression.

These findings are based on source-level tracing, not runtime reproductions. Runtime tests were not run. The five added tests cover open orders with matching prices, base UOM, and a one-minute operation, and do not exercise the cases above.

Comment thread src/Apps/W1/Subcontracting/App/src/Purchase/SubcPurchaseLineExt.Codeunit.al Outdated
Comment thread src/Apps/W1/Subcontracting/App/src/Purchase/SubcPurchaseLineExt.Codeunit.al Outdated
@ChethanT

Copy link
Copy Markdown
Contributor Author

PR Shepherd plan ps-cc34ce23d2666cb9f8cf92bd42ce62692b4290a447a17c6b761b8e18fedc3b4f

  • Provider: github
  • Repository: microsoft/BCApps
  • PR: 11197
  • Generation: 1
  • Source head: 6a3802a
  • Base: d7bab3d
  • Created: 2026-09-09T19:42:07.310307Z
  • Expires: 2026-09-10T19:42:07.310307Z

Summary

{"summary":"Four inline findings are valid from source tracing. The post-transfer repricing call can replace the requisition worksheet's calculated or manually overridden cost; the date subscribers invoke line-discount validation on released orders; and the planned-date equality guard misses lead-time changes that alter Order Date. The fix will preserve worksheet overrides and calculated fallbacks, reprice only automatically selected prices, keep released-order scheduling from changing financial terms, and trigger repricing when the resulting pricing date changes. Regression coverage will include no matching price with nontrivial runtime/UOM conversion, a manual worksheet override, released purchase-order date changes, and lead-time-only movement across a price boundary."}

Approved actions

  • fix-feedback fix -> refs/heads/private/ChethanT/backport-10917-29.x-20260908094110: Fix the four validated pricing and scheduling regressions and add focused regression coverage.
    Payload:
    {"allowed_files":["src/Apps/W1/Subcontracting/App/src/Manufacturing/SubcReqWkshMakeOrd.Codeunit.al","src/Apps/W1/Subcontracting/App/src/Purchase/SubcPurchaseLineExt.Codeunit.al","src/Apps/W1/Subcontracting/Test/Tests/SubcPricingTest.Codeunit.al"],"behavior":"When carrying out a subcontracting requisition line, retain a manually entered Direct Unit Cost and retain the calculated requisition fallback when no applicable subcontractor price exists; only replace an automatically selected worksheet price with the price valid on the final purchase Order Date. Date changes on released subcontracting purchase orders must remain allowed without changing released financial terms. Repricing on open orders must be based on whether the resulting Order Date changed, including lead-time-only rescheduling where Planned Receipt Date is unchanged.","push_destination":"microsoft/BCApps:private/ChethanT/backport-10917-29.x-20260908094110","source_branch":"private/ChethanT/backport-10917-29.x-20260908094110","validation_commands":["git diff --check","pwsh -File build\\scripts\\RunTestsInBcContainer.ps1 -TestType IntegrationTest -parameters <isolated Subcontracting test-app container parameters>; run codeunit 139982 \"Subc. Pricing Test\" including the four new regression scenarios"]}
  • reply-no-price reply -> PRRT_kwDOJh2Tgs6gLBIj: Reply that the no-price fallback regression was fixed and tested.
    Payload:
    {"body":"Fixed in {{commit_url}}. Carry-out now preserves the requisition worksheet's calculated fallback when no applicable subcontractor price exists, instead of replacing it with the routing line's raw rate. Added regression coverage with a nontrivial time/UOM-derived cost."}
    Depends on: fix-feedback
  • react-no-price reaction -> PRRC_kwDOJh2Tgs7rz-4-: Mark the valid no-price finding as useful.
    Payload:
    {"reaction":"+1"}
    Depends on: fix-feedback
  • resolve-no-price resolve -> PRRT_kwDOJh2Tgs6gLBIj: Resolve the no-price fallback thread after the fix and reply are delivered.
    Payload:
    {"resolution":"resolved"}
    Depends on: reply-no-price
  • reply-released-order reply -> PRRT_kwDOJh2Tgs6gLBWx: Reply that released-order scheduling was preserved and tested.
    Payload:
    {"body":"Fixed in {{commit_url}}. Date validation on released subcontracting purchase orders remains allowed and no longer attempts to change released financial terms. Added released-order coverage for Planned Receipt Date and Order Date changes."}
    Depends on: fix-feedback
  • react-released-order reaction -> PRRC_kwDOJh2Tgs7rz_ON: Mark the valid released-order finding as useful.
    Payload:
    {"reaction":"+1"}
    Depends on: fix-feedback
  • resolve-released-order resolve -> PRRT_kwDOJh2Tgs6gLBWx: Resolve the released-order scheduling thread after the fix and reply are delivered.
    Payload:
    {"resolution":"resolved"}
    Depends on: reply-released-order
  • reply-manual-price reply -> PRRT_kwDOJh2Tgs6gLBki: Reply that manual worksheet costs are preserved and tested.
    Payload:
    {"body":"Fixed in {{commit_url}}. Carry-out now distinguishes an automatically selected worksheet price from a manual Direct Unit Cost override, and preserves the manual value. Added a carry-out regression test with an explicit worksheet override."}
    Depends on: fix-feedback
  • react-manual-price reaction -> PRRC_kwDOJh2Tgs7rz_iC: Mark the valid manual-price finding as useful.
    Payload:
    {"reaction":"+1"}
    Depends on: fix-feedback
  • resolve-manual-price resolve -> PRRT_kwDOJh2Tgs6gLBki: Resolve the manual worksheet price thread after the fix and reply are delivered.
    Payload:
    {"resolution":"resolved"}
    Depends on: reply-manual-price
  • reply-pricing-date reply -> PRRT_kwDOJh2Tgs6gLBwD: Reply that repricing now follows the resulting Order Date and is tested.
    Payload:
    {"body":"Fixed in {{commit_url}}. The skip condition now follows whether the resulting Order Date changed, so lead-time-only rescheduling can reprice even when Planned Receipt Date is unchanged. Added a price-boundary regression test for that path."}
    Depends on: fix-feedback
  • react-pricing-date reaction -> PRRC_kwDOJh2Tgs7rz_y1: Mark the valid pricing-date finding as useful.
    Payload:
    {"reaction":"+1"}
    Depends on: fix-feedback
  • resolve-pricing-date resolve -> PRRT_kwDOJh2Tgs6gLBwD: Resolve the resulting-pricing-date thread after the fix and reply are delivered.
    Payload:
    {"resolution":"resolved"}
    Depends on: reply-pricing-date
  • request-rereview reviewer -> attilatoury: Request re-review after every validated finding is fixed and resolved.
    Payload:
    {"body":"\u0040attilatoury, the four findings from your critical review have been addressed with focused regression coverage. Please re-review the latest commit."}
    Depends on: resolve-no-price, resolve-released-order, resolve-manual-price, resolve-pricing-date
  • report-outcome report -> 11197: Post the receipt-based outcome after all approved feedback actions complete.
    Payload:
    {"body":"Report the verified commit, validation results, four thread replies/reactions/resolutions, reviewer follow-up, pipeline state, and any remaining blockers.","location":"conversation"}
    Depends on: request-rereview

approve ps-cc34ce23d2666cb9f8cf92bd42ce62692b4290a447a17c6b761b8e18fedc3b4f
reject ps-cc34ce23d2666cb9f8cf92bd42ce62692b4290a447a17c6b761b8e18fedc3b4f

@ChethanT

Copy link
Copy Markdown
Contributor Author

approve ps-cc34ce23d2666cb9f8cf92bd42ce62692b4290a447a17c6b761b8e18fedc3b4f

Preserve manual and calculated worksheet costs, retain released-order scheduling, and reprice lead-time-only date changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 255f96a1-3a67-418c-9b69-ca50ae31e5b0

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new non-price-list cost calculation can divide by zero on Total Exp. Oper. Output (Qty.), which should be guarded to avoid runtime failures.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Backport to releases/29.x of the subcontracting pricing fix to ensure subcontracting purchase lines are repriced after scheduling/field transfers finalize the effective Order Date, so date-effective subcontractor prices are selected correctly.

Changes:

  • Reapplies subcontractor pricing after requisition-to-purchase-line manufacturing fields are transferred.
  • Reprices subcontracting purchase lines when scheduling-related date validations shift the effective Order Date (Planned Receipt Date / Order Date).
  • Adds regression tests covering backward-scheduled pricing, rescheduling repricing, and preservation of financial terms on released orders.
File summaries
File Description
src/Apps/W1/Subcontracting/Test/Tests/SubcPricingTest.Codeunit.al Adds regression tests and local helper procedures to validate date-effective subcontractor pricing behavior on 29.x.
src/Apps/W1/Subcontracting/App/src/Purchase/SubcPurchaseLineExt.Codeunit.al Subscribes to Purchase Line date validations to trigger subcontracting repricing on schedule changes (with release-status bypass).
src/Apps/W1/Subcontracting/App/src/Purchase/SubcPriceManagement.Codeunit.al Refactors purchase-line price retrieval to support “try price-list cost” logic and adds non-price-list direct-cost calculation.
src/Apps/W1/Subcontracting/App/src/Manufacturing/SubcReqWkshMakeOrd.Codeunit.al Reprices worksheet-created subcontracting purchase lines after requisition fields are transferred, when the original cost was price-list-derived.
Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@alexei-dobriansky

Copy link
Copy Markdown
Contributor

Good Sense Reviewer - Round 1

Recommendation: Request Changes

What this PR does

This change reprices subcontracting purchase lines after requisition fields are copied and after schedule date changes, so Direct Unit Cost follows the final purchase-line Order Date. It also preserves no-price fallback costs, manual worksheet costs, and released-order scheduling behavior.

The functional approach matches the reported pricing-date problem. The make-order publisher was verified on the target branch: it runs after requisition fields are transferred and before the purchase line is inserted. The purchase-line date flow also assigns Order Date from Planned Receipt Date, so checking the resulting Order Date is the right trigger. However, the current build introduces a new analyzer warning that fails the app build, so the PR is not merge-ready yet.

Problem-solution fit

Fit: Strong

The bug says subcontracting pricing can use a date that does not match the final purchase-line Order Date. The diff addresses both creation paths and later schedule changes, and the added tests cover the main date-effective pricing paths plus the follow-up edge cases.

Suggestions

S1 (🔴 High): Build fails on variable order
Move NewLeadTime before the Date variables in this var block, or otherwise sort the declarations by AL type order. The current order introduces AA0021, and the W1 app build fails because new warnings are treated as errors.

Risk assessment and necessity

Risk: The functional regression surface is subcontracting purchase-line pricing, including Direct Unit Cost, worksheet carry-out, and schedule date edits. The code is narrow and guarded by subcontracting, temporary-record, upgrade-context, production-order, operation, and purchase-header status checks. The remaining concrete risk is merge readiness: the current app build fails on the new analyzer warning.

Necessity: The change is required. Without it, a subcontracting purchase line can keep a cost selected for the wrong effective date. The scope is appropriate for a backport once the build-blocking warning is fixed.


[AI-PR-REVIEW] version=1 promptVersion=4 system=github pr=11197 round=1 by=alexei-dobriansky at=2026-09-10T00:18:57.9626275Z lastSha=02e7a0dba2cc27ce4d57cd3896f3509b27fd6aa9 reviewKey=d8d61469faf5a4968b56b1840e67b9ca68006575f3b9791f5df096a178a0c759 suggestions=S1@cac33a80

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 255f96a1-3a67-418c-9b69-ca50ae31e5b0
@ChethanT Chethan Thopaiah (ChethanT) added the Subcontracting Subcontracting related activities label Sep 10, 2026
Guard zero expected output, avoid unnecessary record loads, and cover direct no-price fallback calculations.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 255f96a1-3a67-418c-9b69-ca50ae31e5b0
@ChethanT

Copy link
Copy Markdown
Contributor Author

Applied the accepted #11292 review follow-up in 9f1480b3d4: zero-output fallback guard, pre-lookup applicability guards, partial routing-line loading, and direct no-price fallback coverage for Units, Time, and zero expected output. The suggested two-Get routing lookup was intentionally not adopted because the existing Released|Finished FindFirst is one bounded clustered-key query.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The changes are well-scoped to subcontracting repricing, include safeguards for released documents, and add regression tests covering the key behavioral paths described in the PR.

Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 255f96a1-3a67-418c-9b69-ca50ae31e5b0
@ChethanT

Copy link
Copy Markdown
Contributor Author

Proactively applied the minimum-quantity-tier correction from the main review in 5b6ed25e05. A date/UOM-compatible price whose minimum quantity exceeds the purchase quantity now uses the standard subcontracting fallback, while a matched zero-cost tier remains valid. Regression coverage for both cases is included.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It changes core purchase-line validation/pricing behavior via new event subscribers and pricing fallback logic, which warrants full CI validation and careful human review of downstream behavioral impact.

Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@alexei-dobriansky

Copy link
Copy Markdown
Contributor

Good Sense Reviewer - Round 2

Recommendation: Request Changes

What this PR does

The new commits fix the prior build warning by sorting the test variables, and they extend the no-price fallback so direct purchase-line repricing can fall back when no applicable price tier matches. The main date-effective repricing approach still matches the reported bug, and the target-branch event timing was verified.

The new minimum-quantity fallback is incomplete. It handles direct purchase-line repricing, but the worksheet pricing path still ignores the new GetPriceByUOM Boolean result and can keep a wrong zero cost.

Status of previous suggestions
ID Title Status Author response
S1 Build fails on variable order Addressed Fixed in fa1cb2f08e.
New observations (commits since round 1)

S2 (🔴 High): Worksheet minimum tier still zeroes cost
Use the new GetPriceByUOM Boolean result in GetSubcPriceForReqLine too. Otherwise a worksheet line with only a date/UOM-compatible price above its quantity still writes Direct Unit Cost as zero, and carry-out preserves that wrong cost instead of the standard fallback.

Risk assessment and necessity

Risk: The regression surface is subcontracting purchase-line pricing, especially Direct Unit Cost on purchase orders created from the worksheet. The new subscribers are guarded and the relevant publisher timing was verified on the target branch, but the minimum-quantity path can still persist the wrong cost for worksheet-created orders. git diff --check passes; app builds are still pending.

Necessity: The change is required because subcontracting lines can otherwise keep a price selected for the wrong effective date. The backport scope is appropriate, but the minimum-quantity fallback must cover both direct purchase-line pricing and worksheet pricing before merge.


[AI-PR-REVIEW] version=1 promptVersion=4 system=github pr=11197 round=2 by=alexei-dobriansky at=2026-09-10T12:27:45.9426331Z lastSha=5b6ed25e050acecf69cb53ba1344f046446ec5ae reviewKey=1ba5c38c0f47d3eee2e1093717eadfe110540094c5eff34b140ac3308621b4b8 suggestions=S1@cac33a80:addressed,S2@d67ef92b:new parentRound=1

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 255f96a1-3a67-418c-9b69-ca50ae31e5b0
@ChethanT

Copy link
Copy Markdown
Contributor Author

Synchronized the latest #11292 review fixes in 2e5568349e. This includes requisition-context automatic-cost detection, final purchase-line date pricing, minimum-quantity fallback handling, strict missing-routing diagnostics, and release-compatible regression tests.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A pricing path now exits early without clearing requisition-line subcontracting price-list fields, which can leave stale state when no tier is applicable.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment on lines +488 to +489
if not GetPriceByUOM(SubcontractorPrice, PriceListQty, PriceListCost) then
exit;
@alexei-dobriansky

Copy link
Copy Markdown
Contributor

Good Sense Reviewer - Round 3

Recommendation: Request Changes

What this PR does

The latest commits apply the follow-up fixes for automatic worksheet cost detection, final purchase-line date pricing, minimum-quantity fallback, strict routing lookup, and release-compatible tests. The previous worksheet minimum-tier problem is now covered: requisition pricing consumes the GetPriceByUOM match result, and the new test keeps the calculated fallback when no tier applies.

The target-branch publishers were verified. The requisition-to-purchase event runs after requisition fields are transferred and before line insert, and the purchase-line date publisher recalculates Order Date before the after-validate subscribers run. However, the test app does not compile because the new tests call LibraryRandom without declaring that codeunit variable.

Status of previous suggestions
ID Title Status Author response
S1 Build fails on variable order Addressed The variable-order warning was removed before this round.
S2 Worksheet minimum tier still zeroes cost Addressed The latest change uses the GetPriceByUOM Boolean result on the requisition-line path and adds fallback coverage.
New observations (commits since round 2)

S3 (🔴 High): Test app misses LibraryRandom variable
Add LibraryRandom: Codeunit "Library - Random"; to the test codeunit, in the correct AL variable order. The latest build reports AL0118 for each new LibraryRandom.RandDecInRange call, so the Subcontracting Test app cannot compile.

Risk assessment and necessity

Risk: The functional regression surface is subcontracting purchase-line pricing, including worksheet carry-out, minimum-quantity fallback, released-order scheduling, and date-effective prices. The code changes are narrow and guarded by subcontracting, production-order, operation, temporary-record, upgrade-context, and purchase-header status checks. The current concrete risk is merge readiness: the Subcontracting Test app fails compilation because a new test dependency is missing.

Necessity: The change is required because subcontracting lines can otherwise use a price selected for a date that does not match the final purchase-line Order Date. The scope is appropriate for a backport once the compile blocker is fixed.


[AI-PR-REVIEW] version=1 promptVersion=4 system=github pr=11197 round=3 by=alexei-dobriansky at=2026-09-11T09:55:14.4808300Z lastSha=2e5568349e4213d049691208199d49e0cd9914e8 reviewKey=3415b9110d0d077ebdbe08401e707eea1ba0dc896cf2a5c498fe9806f81f72ed suggestions=S1@cac33a80:addressed,S2@d67ef92b:addressed,S3@0f191555:new parentRound=2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AL: Apps (W1) Add-on apps for W1 Subcontracting Subcontracting related activities Team: SCM GitHub request for SCM area

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants