I have a requirement when we are opening the Product Receipt page (PurchEditLines), the Quantity (RecieveNow) should default to zero. Currently it defaults to the Quantity Ordered Value
We are navigating to this via: AP–>PO–>product Receipt
So far this is my code for the PurchEditLines:
[ExtensionOf(formStr(PurchEditLines))]
final class PurchEditLines_Extension
{
/// Prevent auto-population of RecieveNow when the form loads
[FormDataSourceEventHandler(formDataSourceStr(PurchEditLines, PurchParmLine), FormDataSourceEventType::Activated)]
public static void PurchParmLine_OnActivated(FormDataSource sender, FormDataSourceEventArgs e)
{
PurchParmLine purchParmLine = sender.cursor() as PurchParmLine;
if (purchParmLine)
{
purchParmLine.ReceiveNow = 0; // Ensure RecieveNow does not auto-populate
}
}
/// Add a warning when clicking OK to prevent unintended full receipts
[FormControlEventHandler(formControlStr(PurchEditLines, OK), FormControlEventType::Clicked)]
public static void OK_OnClicked(FormControl sender, FormControlEventArgs e)
{
FormDataSource purchParmLineDS = sender.formRun().dataSource(formDataSourceStr(PurchEditLines, PurchParmLine));
PurchParmLine purchParmLine;
str warning = "This purchase order has line(s) that are being received in full. Please confirm if this is correct.";
str cancel = "Posting has been canceled by the user.";
boolean hasZeroRemainAfter = false;
while select purchParmLine where purchParmLine.RemainAfter == 0
{
hasZeroRemainAfter = true;
break;
}
if (hasZeroRemainAfter)
{
DialogButton userChoice = Box::yesNo(warning, DialogButton::No, "Purchase Order Receipt Warning");
if (userChoice == DialogButton::No)
{
throw error(cancel); // Prevent posting
}
}
}
}
However the Quantity defaults to blank, its not registering as zero. It is also not doing this for all lines when a PO has more than one line.
The whole idea is wrong. You’re completely ignoring the existing business logic generating PurchParmLine records and determining the quantity, you change the value just on the selected record (which doesn’t meet your requirements), you don’t save the change…
The records are created by classes like PurchFormletterParmDataReceiptsList.
The validation is wrong too. This business logic doesn’t belong to Clicked event, you validate the data after posting, you select records regardless of ParmId, you waste resources by using while select to check whether there is a record with RemainAfter = 0…
You’ll need to make your changes more carefully and test whether your code works.
Regarding the quantity the requirement is that it should default to zero upon opening, so that the users can determine the quantity itself. Right now the logic seems to be just duplicating the logic for Quantity Ordered, and the values are the same between the two columns. However we are not wanting that, we want it to show as zero upon opening the PurchEditLines form. Is it just a matter of overriding the logic from a different class?
Right now i’m looking at some of the logic used to generate this field (ReceiveNow), however I’m only wanting to edit the value for this specific form, PurchEditLines. The ask is that whenever a user Selects a PO and Selects Product Reciept, the Quantity Field should be defaulting to Zero. It’s currently defaulting to the Quantity Ordered Value. So that was why I was thinking of editing on the form itself.
Regarding the validation, this was how the users were wanting it to work. When attempting to post the warning message needs to appear. Not after posting
No, the logic isn’t “just duplicating the logic for Quantity Ordered”. You’ll get different behavior if you use a different value of the Quantity parameter:
When you change the parameter, the records are re-generated, which isn’t covered by your current design. You keep thinking about form opening, but that’s not correct. You need to focus on the data generation, regardless of when it’s called.
Now, when you understand that there are other options than Quantity = Ordered quantity, you need to decide whether you want apply your logic only when this particular setup is used, or in other cases as well.
Sorry I have not been very clear on what ive been looking for. in this specific instance we are only trying to update the ReceiveNow field for when SpecQty is Ordered Quantity. The requirement is that on Ordered quantity, on the line level the quantity field (ReceiveNow) has to default to zero. When I mentioned Quantity Ordered I meant on the line section in purcheditline the Qty field from PurchParmLine.
And if the user decided to receive in full, we put in a warning message asking the user if they want to proceed (which I have working). Just not too sure what direction to go in regarding the RecieveNow value at the line level.
You want your logic just for Product receipt and Ordered quantity, but you don’t have either in your code. It would run for all types of posting (confirmation, invoice…) and with any quantity specification.
The type of posting will be handled when you put your logic at the right place. There are subclasses for each type of posting and you just need to do it in the right subclass. For quantity, you need to use a condition in code.
For example, you could put your logic to PurchFormletterParmDataPackingSlip.setParmLine() and run it only if purchParmUpdate.SpecQty == PurchUpdate::All.
[ExtensionOf(classStr(PurchFormletterParmDataPackingSlip))]
public final class PurchFormletterParmDataPackingSlip_DPRExtensions_Extension
{
protected void setParmLine(PurchLine _purchLine, VendDocumentLineMap _parmLine)
{
next setParmLine(_purchLine, _parmLine);
PurchParmLine purchParmLine = _parmLine.parmParmLine();
PurchParmUpdate purchParmUpdate = _parmLine.parmParmUpdate();
if (purchParmLine && purchParmUpdate && purchParmUpdate.SpecQty == PurchUpdate::All)
{
// Only clear ReceiveNow if it's defaulting to QtyOrdered
if (purchParmLine.ReceiveNow == _purchLine.QtyOrdered)
{
purchParmLine.ReceiveNow = 0;
}
}
}
}
I’ve been getting issues with this when trying to open the Product Receipt in the PO page. Getting Update has been canceled. In the initial code I posted I was seeing blank values instead of zeroes, but now its not really loading.
Use the debugger to find more details about the problem. By the way, you don’t need the two first lines of your code. purchParmLine is already in _parmLine parameter and purchParmUpdate is an instance variable.
From which I can tell is because parmParmLine()` is returning null in certain scenarios. I had tried to update the code, currently this is what I have:
[ExtensionOf(classStr(PurchFormletterParmDataPackingSlip))]
public final class PurchFormletterParmDataPackingSlip_DPRExtensions_Extension
{
protected void setParmLine(PurchLine _purchLine, VendDocumentLineMap _parmLine)
{
// If it’s a PurchParmLine, and we’re using ‘Ordered Quantity’, prepare to set ReceiveNow to 0
PurchParmLine purchParmLine = _parmLine as PurchParmLine;
PurchParmUpdate purchParmUpdate = this.parmParmUpdate();
if (purchParmLine && purchParmUpdate && purchParmUpdate.SpecQty == PurchUpdate::All)
{
if (_purchLine.QtyOrdered && purchParmLine.ReceiveNow == _purchLine.QtyOrdered)
{
// Override quantity before calling the next handler
_parmLine.parmQty(0);
}
}
next setParmLine(_purchLine, _parmLine);
}
}
But i’m still getting Update has been canceled.
Stack trace: Call to TTSCOMMIT without first calling TTSBEGIN errors when trying to open the Product Reciept form
i’m assuming its because i’m trying to “patch” values like ReceiveNow onto existing calculations? Is there something else I could be doing? Would extending on PurchFormLetter_PackingSlip make more sense?
I’m a bit new to the D365 development landscape so any help is appreciated
Let me repost your code to make it easier to read:
[ExtensionOf(classStr(PurchFormletterParmDataPackingSlip))]
public final class PurchFormLetterParmDataPackingSlip_DPRExtensions_Extension
{
protected void setParmLine(PurchLine _purchLine, VendDocumentLineMap _parmLine)
{
// If it’s a PurchParmLine, and we’re using ‘Ordered Quantity’, prepare to set ReceiveNow to 0
PurchParmLine purchParmLine = _parmLine as PurchParmLine;
PurchParmUpdate purchParmUpdate = this.parmParmUpdate();
if (purchParmLine && purchParmUpdate && purchParmUpdate.SpecQty == PurchUpdate::All)
{
if (_purchLine.QtyOrdered && purchParmLine.ReceiveNow == _purchLine.QtyOrdered)
{
// Override quantity before calling the next handler
_parmLine.parmQty(0);
}
}
next setParmLine(_purchLine, _parmLine);
}
}
Now let me simplify it. As I mentioned before, some of your code isn’t needed at all. I also removed the condition for QtyOrdered, because it’s not in your business requirement. By the way, the parmQty() method doesn’t seem to exists - does your code really works at runtime?
Here is my suggestion:
[ExtensionOf(classStr(PurchFormletterParmDataPackingSlip))]
internal final class PurchFormLetterParmDataPackingSlip_DPRExtensions_Extension
{
protected void setParmLine(PurchLine _purchLine, VendDocumentLineMap _parmLine)
{
next setParmLine(_purchLine, _parmLine);
if (purchParmUpdate.SpecQty == PurchUpdate::All)
{
_parmLine.ReceiveNow = 0;
}
}
Note that there are other related fields (InventNow, RemainAfter, RemainBefore, RemainAfterInvent, RemainAfterInvent), but let’s focus on a single field for now.
We just set a value of the field; we don’t do anything with transactions. If you’re still getting the error about TTSCOMMIT, I think it’s caused by some other changes of yours.
Could that be related to not handling InventNow and RemainAfter as well when setting ReceiveNow to 0? Just wanted to check if that might be causing the issue. Since this is only setting the RecieveNow value, wonder if the attempt to override the value is causing some issue? From some of my testing it looks like it has something to do with this: purchParmUpdate.SpecQty == PurchUpdate::All
Other code fixes that i’m trying with that condition only are for some reason clearing all the lines from the line section in the form
The Delivery Remainder here should show as 210. If I manually enter 0 then the Delivery remainder shows up. But if I try to set it as zero the lines will disappear for some reason
Your description suggests that that lines with nothing to post aren’t shown in the form. If so, it means that you’ve designed a solution that currently can’t work. You’d have to change this behavior.
If you want to know what happens in the standard code, simply use the debugger and take a look.
Indeed, 0.00001 isn’t the same thing as 0.
By the way, please use wrap source code in ``` when posting it here (put the backticks at separate lines). Code will them be displayed like this:
[ExtensionOf(classStr(PurchFormletterParmDataPackingSlip))]
internal final class PurchFormLetterParmDataPackingSlip_DPRExtensions_Extension
{
protected void setParmLine(PurchLine _purchLine, VendDocumentLineMap _parmLine)
instead of
[ExtensionOf(classStr(PurchFormletterParmDataPackingSlip))]
internal final class PurchFormLetterParmDataPackingSlip_DPRExtensions_Extension
{
protected void setParmLine(PurchLine _purchLine, VendDocumentLineMap _parmLine)
In a PO with six lines, lines 5 and 6 are missing. These are lines where nothing has been received yet. From debugging, it looks like the issue might be related to setting ReceiveNow to zero in my code.
Here’s my extension code:
[ExtensionOf(classStr(PurchFormletterParmDataPackingSlip))]
internal final class PurchFormLetterParmDataPackingSlip_Extensions
{
protected void setParmLine(PurchLine _purchLine, VendDocumentLineMap _parmLine)
{
next setParmLine(_purchLine, _parmLine);
PurchParmLine purchParmLine = _parmLine as PurchParmLine;
if (purchParmUpdate.SpecQty == PurchUpdate::All)
{
purchParmLine.ReceiveNow = 0;
purchParmLine.modifiedField(fieldNum(PurchParmLine, ReceiveNow)); // <- This triggers RemainAfter calc
}
}
}
I suspect that the call to modifiedField(fieldNum(PurchParmLine, ReceiveNow)) might be causing these lines to be skipped. However, I need this call to trigger the RemainAfter calculation.
That said, the missing lines have quantities ordered of 10 and 1, so setting ReceiveNow = 0 shouldn’t be causing them to be filtered out. I’ve seen other lines with similar quantities still generate correctly.
Do you have any insight? Could there be another condition in the system that prevents lines from generating in this scenario?
Which lines and which quantity will be included depends on the Quantity parameter (discussed above), and maybe some other logic as well. You didn’t tell us which setup you use to generate the lines; I’m assuming that the order lines aren’t eligible for posting according to your value of the Quantity parameter. This parameter is critical, you’re making a big mistake by ignoring it.
This is used for the Ordered Quantity parameter. Which is why I have the condition set to SpecQty=All, which is ordered quantity.. As that was the requirement, for ordered quantity parameter, the receivenow value in the lines section should default to zero.
This isn’t an issue with the parameter as when I adjust my code to set receivenow to 1, the missing lines appear. Which is what is confusing me. The debugger hadn’t really given me anything concrete on what’s causing these issues. Do you have any insight on what maybe causing these lines to not generate?
Ah, OK, you mean still the problem. I thought you’re talking about something new.
You’ll need to continue your debugging. It seems that you don’t know how, so let me give you a suggestion. For example, look at the call stack inserting the line when quantity is 1 and put breakpoints to those methods. Then run the logic with quantity 0 and check which methods weren’t called. Then debug the method that was supposed to call the next method of the given call stack and check why it didn’t happen.
It is a different problem, since I have the default behavior set. It’s just that certain lines are being excluded for some reason. Like in image I posted,
This PO has 6 lines. When I generate the Product Reciept only 4 of these are generated with the default quantity set to zero. But the last two lines are not generating. And these are lines that are not received in full.
Can you check with your users if this would work instead?
The users can enter what is being received on the purchase order lines before opening the Posting Product Receipt Screen. There is a field on the purchase order lines called “Receive Now” - they could enter the qty being received for each line there.
When they open the Posting Product Receipt Screen they should choose the Quantity Parameter to be “Receive Now Quantity” = that will then pull through the quantities in step 1.