Eddie Monster
15th September 2023, 16:32
Looking for a little guidance. I used to program in Baan, but we have moved to LNCE and during that project I had other responsibilities. I am now getting back into the development side once again (a little rusty). I am attempting to make a Public Interface function call using PlannedPeggingRelations.FindSupplyForOrder(). The code compiles fine. If I run the session without debugging it completes, but no values are returned. If I debug while running the session my entire connection to LNCE bombs out with Java errors so I'm having great difficulty tracing down what the issue is. I expect it is my code but am not sure what is wrong. I'm hoping someone with a little more experience may be able to be a second set of eyes. I have hardcoded the function with values in an attempt to limit the possibility of errors.
I've also created a debug bshell and from what I can see (not an expert) there is nothing that sticks out to indicate a problem.
Any direction or guidance would be appreciated. For reference the documentation for this specific public interface is attached.
I'm expecting that the array values will be filled once the function is called.
Here is my code:
function get.pegged.order()
{
#pragma used dll "ocpextrrpapi"
#pragma used dll otcextextapi
domain cpcom.plnc iPlanningScenario
domain tckoor iOrderType
domain c****o iOrderNumber
domain tcpono iOrderLine
domain tcpono iSequence
domain tcpono iMaterialPosition
domain tccom.long oParentTransactionArray(100)
domain tcncmp oParentCompanyArray(100)
domain cpcom.plnc oParentScenarioArray(100) fixed
domain tccom.long oChildTransactionArray(100)
domain tcncmp oChildCompanyArray(100)
domain cpcom.plnc oChildScenarioArray(100) fixed
domain tcmcs.s999m oExceptionMessage mb
long oExceptionID
iPlanningScenario = "ACT"
iOrderType = tckoor.act.sls
iOrderNumber = "SL0012216" | r.orno
iOrderLine = 10 | r.pono
iSequence = 0 | r.sqnb
iMaterialPosition = 0
if PlannedPeggingRelations.FindSupplyForOrder(
iPlanningScenario,
iOrderType,
iOrderNumber,
iOrderLine,
ISequence,
iMaterialPosition,
oParentTransactionArray,
oParentCompanyArray,
oParentScenarioArray,
oChildTransactionArray,
oChildCompanyArray,
oChildScenarioArray,
oExceptionMessage,
oExceptionID) <> 0 then
Exception.Delete(oExceptionID)
message(oExceptionMessage)
else
message("TEST")
endif
}
Eddie Monster
15th September 2023, 17:43
Just a note the domain for iOrderNumber is being replaced by *** I'm guessing due to some sort of censoring. The domain is c/p/o/r/n/o.
vamsi_gujjula
15th September 2023, 21:18
May be you can post the debug bshell log.
should you be using a based output variables ?
RieseUSA
16th September 2023, 03:45
As Vamsi pointed out, the problem is possibly that you are not using 'based' variables for the array as documented in the Public Interface guide:
"...
technical: Output arrays must be defined as based arrays.
..."
The logic of the PlannedPeggingRelations.FindSupplyForOrder() function will try to allocate memory to those arguments, but if they are not 'based', it will not work.
I believe that it needs to be like this:
domain tccom.long oParentTransactionArray(1) based
domain tcncmp oParentCompanyArray(1) based
domain cpcom.plnc oParentScenarioArray(1) based
domain tccom.long oChildTransactionArray(1) based
domain tcncmp oChildCompanyArray(1) based
domain cpcom.plnc oChildScenarioArray(1) based
Another remark, public interface functions can return several messages. Your logic would currently only return the last one, which might not provide the key information to an error.
Sample Public Interface call:
#pragma used dll "otcextextapi"
#pragma used dll "otcextemmapi"
long exception.id, i
domain tcmcs.s999m exception.message
if Common.ConvertAmount(..., exception.message, exception.id) <> 0 then
|* Exception(s) found.
for i = 1 to Exception.NumberOfMessages(exception.id)
dal.set.error.message("@"& Exception.GetMessage(i))
endfor
Exception.Delete(exception.id)
return(DALHOOKERROR)
else
|* Call was successful. Exception messages could exist!
Exception.Delete(exception.id)
endif
We are unfortunately not using the cp functionality and I cannot test this Public Interface myself.
Yours,
Stephan
OmeLuuk
19th September 2023, 11:30
Apart from the based variables (which makes sense) which you can allocate before your public interface call, like so (do not forget the release.mem afterwards) |discount matrices allocation
alloc.mem(ps.Rate, 3)
alloc.mem(ps.RateFactor, 3)
alloc.mem(ps.DiscountMatrixType, 11)
alloc.mem(ps.DiscountOrigin, 11)
alloc.mem(ps.DiscountMatrixDefinition, 9, 11)
alloc.mem(ps.DiscountMatrixSequence, 11)
alloc.mem(ps.DiscountPercentage, 11)
alloc.mem(ps.DiscountAmount, 11)
alloc.mem(ps.DiscountCode, 3, 11)
alloc.mem(ps.DiscountMethod, 11)
alloc.mem(ps.DiscountSchedule, 9, 11)NOTE: These are public arguments for the PriceSimulator Public Interface Function, you can derive dimensions you need from your function description (argument list).
I found something strange with this construction:
From the extension of the pricebook table (tdpcg031) via an "ITEM-BOD" call the public interface of the pricesimulator (Pricing.SimulateSalesPrice) is called. But this call changed the current actual record of the pricebook table, so after the ITEM-BOD was called it continued with a wrong record causing all kind of strange errors.
I was able to resolve that by using this construction: if in.focus.pricebook() and
(mode=DAL_NEW or some.change()) then
if rdi.table("tdpcg031",duml,duml,len.ttdalt031,len.ttdalt031.real)=0 then
alloc.mem(rcd.ttdalt031, len.ttdalt031)
tbl.ttdalt031 = db.bind("ttdpcg031", rcd.ttdalt031)
rcd.ttdalt031 = rcd.ttdpcg031
ret.val=tcint.dlltcbod.publish.item.master.common.replace(tdpcg031.item)
db.record.to.columns(tbl.ttdalt031)
db.unbind(tbl.ttdalt031)
free.mem(rcd.ttdalt031)
endif
endif
In plain text: copy the recordbuffer of the current record into a buffer and restore the record state based on this flash copy to the previous state afterwards. Now the public interface can mess up record pointer but we will continue where we were as if no messing around happened.
So: see if your record state of the current record remains unchanged after calling the public interface. If it changes, it may also yield unpredictable results.
OmeLuuk
19th September 2023, 12:13
... Now the public interface can mess up record pointer but we will continue where we were as if no messing around happened.Where my doubt still is: what about the "state" of the record in terms of STP. The exact data content is restored but what about an update flag or retry variables around this record? "you can reconstruct, but you cannot turn back time"
Eddie Monster
21st September 2023, 23:11
I apologize for the late response; I've been pulled in many different directions this week.
This is a wealth of information! I appreciate this very much! I will review this over the next few days and let you know how it goes.
OmeLuuk
23rd September 2023, 22:18
I apologize for the late response; I've been pulled in many different directions this week.
This is a wealth of information! I appreciate this very much! I will review this over the next few days and let you know how it goes.Probably defining the argument list (and reading the error messages stack as mentioned by others) will help you to get things running. My addition was a side track that I wanted to have documented here as well, because it took some time to figure out the reason and "solution" (sooner: work around).
Eddie Monster
4th October 2023, 13:58
Just wanted to provide a quick update. Your suggestions for the 'based' variables fixed the majority of my issues. So far, the rest of the issues I've encountered are simply related to my being 'rusty' on Baan/LN development. So a big Thank You for your help.
One clarification I do have... would the error handling be a little different when using extensibiltiy vs. LN Studio? My understanding is that the DAL related syntax would be used in conjunction with extensions. For this session I'm using LN studio. Would the error handling change with this session?