Partial receipts are a small business rule with consequences across purchasing, inventory, and accounts payable. In Microsoft Dynamics 365 Business Central, a quantity-validation mistake can allow an extension to calculate the wrong remaining quantity or reject a legitimate receipt. ERP consulting services need to define that behavior before developers implement it. In this walkthrough, we will encode a simple receipt rule in AL and test its expected outcomes.
Prerequisites
- ERP consulting services for Microsoft Dynamics 365 Business Central development sandbox.
- Visual Studio Code with the Microsoft AL Language extension.
- An AL project targeting Business Central runtime
15.0or later. - An available object ID range for your extension.
- A test environment where you can compile and execute test codeunits.
The example uses core AL language features and does not require an external library. Microsoft documents the test-codeunit model in its official AL testing guide.
Why the obvious approach fails
A common mistake is to treat receipt validation as a single subtraction operation. The arithmetic is correct, but the business rule is incomplete.
Consider this fragment:
RemainingQty := OrderedQty - ReceivedQty;
This is a fragment, not a complete AL object. It assumes both quantities are valid and that the receipt cannot exceed the order quantity.
If OrderedQty is 10 and ReceivedQty is 12, the result is -2. The calculation has no knowledge of whether that outcome is permitted by the business process.
The opposite mistake is rejecting every receipt that differs from the ordered quantity. That prevents legitimate partial deliveries.
The first consulting decision is therefore not which function to write. It is defining the allowed states: zero receipt, partial receipt, full receipt, negative quantities, and over-receipt. Those states become our acceptance criteria.
Step 1: Put the quantity rule in one codeunit
We will separate the calculation from the page or posting workflow. This keeps the rule independently testable and prevents multiple UI entry points from implementing different versions.
Create a file named ReceiptQtyRules.Codeunit.al:
codeunit 50100 "Receipt Qty Rules"
{
procedure GetRemainingQty(
OrderedQty: Decimal;
ReceivedQty: Decimal
): Decimal
begin
if OrderedQty < 0 then
Error('Ordered quantity cannot be negative.');
if ReceivedQty < 0 then
Error('Received quantity cannot be negative.');
if ReceivedQty > OrderedQty then
Error('Received quantity cannot exceed ordered quantity.');
exit(OrderedQty - ReceivedQty);
end;
}
This codeunit defines a specific policy: receipts can be partial, but negative quantities and quantities above the ordered amount are invalid. Confirm that policy with the business owner before connecting it to an actual posting process.
Step 2: Turn the business rules into automated tests
A successful compilation proves that the code is syntactically valid. It does not prove that the rule handles the business cases correctly.
Create a separate test codeunit named ReceiptQtyRulesTests.Codeunit.al. The tests below cover a partial receipt, a complete receipt, and an untouched order.
codeunit 50101 "Receipt Qty Rules Tests"
{
Subtype = Test;
[Test]
procedure PartialReceiptReturnsRemainingQty()
var
ReceiptRules: Codeunit "Receipt Qty Rules";
begin
if ReceiptRules.GetRemainingQty(10, 4) <> 6 then
Error('Partial receipt returned an incorrect quantity.');
end;
[Test]
procedure FullReceiptReturnsZero()
var
ReceiptRules: Codeunit "Receipt Qty Rules";
begin
if ReceiptRules.GetRemainingQty(10, 10) <> 0 then
Error('Full receipt should leave zero quantity.');
end;
[Test]
procedure ZeroReceiptReturnsOrderedQty()
var
ReceiptRules: Codeunit "Receipt Qty Rules";
begin
if ReceiptRules.GetRemainingQty(10, 0) <> 10 then
Error('Zero receipt should leave ordered quantity.');
end;
}
Each test fails when its expected result does not match the returned value. The tests exercise the business rule directly, without requiring a purchase order page or a warehouse workflow.
Step 3: Verify the rejection paths
The first three tests cover valid quantities. We must also verify that invalid inputs trigger errors rather than silently returning negative balances.
In ERP consulting services Business Central test codeunits support error assertions through the test framework. For this small example, you can add a dedicated error-handling test using the appropriate assertion codeunit available in your project's test dependencies. Confirm the exact assertion API and dependency version before adding it.
At minimum, manually verify these cases in the development sandbox:
| Ordered | Received | Expected behavior |
|---|---|---|
| 10 | 4 | Remaining quantity is 6 |
| 10 | 10 | Remaining quantity is 0 |
| 10 | 0 | Remaining quantity is 10 |
| 10 | 12 | Reject the receipt |
| 10 | -1 | Reject the receipt |
| -1 | 0 | Reject the order quantity |
The table is the acceptance matrix, not a substitute for automated negative-path tests. The over-receipt rule may differ when a business explicitly permits over-delivery within a defined tolerance.
Step 4: Compile and execute the tests
Compile the extension in Visual Studio Code using the AL development workflow. Then run the test codeunit in a Business Central sandbox with the test runner and test dependencies configured.
The expected result is three passing tests. If a test fails, inspect the actual quantity and the error message before changing the implementation. Do not weaken an assertion to make a build pass without checking the intended business rule.
For continuous integration, compile the extension and execute its test suite before promoting the package to another environment. The exact command depends on the installed AL tooling and Business Central environment. Pin the tool version in your pipeline rather than assuming every developer uses the same release.
Trade-offs and limitations
The example is intentionally small. It isolates one quantity rule, but it does not implement a complete purchasing or warehouse process.
First, a receipt quantity is not always the same as the quantity invoiced or the quantity physically available. Business Central's posting workflow, unit-of-measure conversions, and warehouse handling may impose additional rules. A helper function cannot replace validation against those records.
Second, some businesses allow over-receipts within a tolerance. The example rejects every quantity above the ordered amount, so that policy would require an explicit tolerance rule and additional tests.
Third, the example does not prevent concurrent processes from changing the underlying order. A real posting operation must use the platform's established transaction and validation behavior rather than trusting a previously calculated remaining quantity.
Finally, a passing unit test does not prove that a complete purchase receipt posts correctly. Integration tests must verify the relevant records, posting behavior, inventory effects, and financial consequences.
At Oodles, we connect business requirements with practical software engineering decisions to help teams define, build, and test ERP extensions.
Real-world application: From consulting scope to testable AL rules
We implemented this principle in a Business Central project for a logistics client, where the agreed delivery scope included approximately 62 AL extensions over an 18-week plan.
The delivery plan used two-week sprints with separate development, quality assurance, and project management responsibilities. That scope required more than listing extensions. Each extension needed a defined purpose, an agreed boundary, and a testable outcome.
For a receipt-related requirement, that means documenting what happens when a shipment arrives partially, exceeds the expected quantity, or conflicts with the purchase order. The acceptance criteria must distinguish valid exceptions from errors before development begins.
The ERP consulting services documented project scope provides two verified planning figures: approximately 62 extensions and 18 weeks. We do not have a verified defect reduction, processing-time improvement, or cost saving to report.
This is where ERP consulting services connect business analysis to engineering. A clear requirement gives developers a rule to implement and testers a condition to verify. It also gives stakeholders a basis for deciding whether a requested behavior belongs in the original scope or requires an approved change.
Our ERP Consulting Services explains the broader context of building ERP solutions around business requirements. The same discipline applies whether an extension changes purchasing, inventory, or financial workflows.
Key takeaways
- Define valid business states before implementing quantity calculations.
- Keep reusable business rules separate from page and posting workflows.
- Test partial, complete, zero, and invalid receipt quantities.
- Confirm over-receipt policy with the business owner before enforcing a hard limit.
- Treat unit tests as one layer of validation, not proof of end-to-end posting correctness.
- Require measurable acceptance criteria for every material ERP extension.
If you have encountered an AL testing edge case around partial receipts, posting validation, or warehouse quantities, share the scenario and expected behavior. Comparing those cases is a useful way to improve acceptance criteria before the next release.
Should partial receipt validation run on the page or in a codeunit?
A reusable business rule belongs in a testable codeunit or an appropriate existing business-logic component. Page-level validation can improve user feedback, but it should not be the only protection for a rule that must hold across multiple entry points.
In ERP Consulting Services Can Business Central allow receipt quantities above the ordered amount?
ERP consulting services that depends on the configured process and the applicable business rules. If over-receipts are permitted, define the tolerance and test the boundary values. Do not copy the strict rejection rule into a process that explicitly permits controlled over-delivery.
Why does a passing AL unit test not guarantee successful posting?
A unit test verifies the specific logic it executes. Actual posting may involve inventory entries, warehouse records, permissions, and other validations. Use integration tests in a sandbox to verify those interactions.
Should receipt rules be duplicated across extensions?
Avoid duplicating the same business rule when a shared component or standard Business Central behavior can enforce it appropriately. However, reuse must respect the application's extension boundaries and posting events. Review the actual dependencies before extracting a common component.
In ERP Consulting Services How should developers test an ERP extension after a platform update?
Compile against the target platform's supported symbols, rerun automated tests, and exercise critical business workflows in a sandbox. Also review changed APIs and dependencies. Pin tooling and runtime versions so the test results are reproducible.
Top comments (0)