dorleta
20th September 2023, 14:07
I try to load the multilevel item structure using the this public interface but I only get the first level.
I tried everything with the arrays definition.
function carga.estructura.2()
{
|domain tccprj oProject(100) based
|domain tccwar oWarehouse(100) based
|domain tcitem oItem(100) based
|domain tcyesno oCustomizable(100) based
|domain tcpono oPositionNumber(100) based
|domain tcqiv1 oBomQuantity(100) based
string oProject(1,100) based
string oWarehouse(1,100) based
string oItem(1,100) based
domain tcyesno oCustomizable(100) based
domain tcpono oPositionNumber(100) based
domain tcqiv1 oBomQuantity(100) based
long oNumberOfMaterials
domain tcmcs.s999m oExceptionMessage
long oExceptionID
long i
long ret
domain tcitem item
domain tcqrd1 quan
ret = JobShopBillOfMaterial.Explode(
"",
txsls010.item,
"", | iBillOfMaterialCode,
"", | iRevision,
0, | iEffectivityUnit,
utc.num(), | iReferenceDate,
10, | iExplosionDepth,
true, | iMergeComponents,
false, | iApplyScrapYield,
true, | iExplodeLowestPhantoms,
oProject,
oWarehouse,
oItem,
oCustomizable,
oPositionNumber,
oBomQuantity,
oNumberOfMaterials,
oExceptionMessage,
oExceptionID )
for i = 1 to 100
item = oitem(1, i)
quan = oBomQuantity(i)
endfor
endselect
RieseUSA
21st September 2023, 02:20
The following works for me, e.g., components from two BOM levels are returned, for an item that has the Classic BOM (tibom010). Job Shop by Site is In Preparation and is not Active yet on the environment.
function long public.interface()
{
#pragma used dll "otcextextapi" |* Public Interfaces for tcext
#pragma used dll "otiextbomapi" |* Public Interfaces for tibom
long l.counter
domain tccprj oProject(1) based
domain tccwar oWarehouse(1) based
domain tcitem oItem(1) based
domain tcyesno oCustomizable(1) based
domain tcpono oPositionNumber(1) based
domain tcqiv1 oBomQuantity(1) based
long oNumberOfMaterials
domain tcmcs.str999m l.exception.message
long l.exception.id
long l.exception.message.counter
domain tcitem l.item
domain tcqiv1 l.quantity
if JobShopBillOfMaterial.Explode(
"", |* iSite
"100BX91900002981827", |* iProduct
"", |* iBillOfMaterialCode
"", |* iRevision
0, |* iEffectivityUnit
utc.num(), |* iReferenceDate
10, |* iExplosionDepth
true, |* iMergeComponents
false, |* iApplyScrapYield
true, |* iExplodeLowestPhantoms
oProject, |* ref
oWarehouse, |* ref
oItem, |* ref
oCustomizable, |* ref
oPositionNumber, |* ref
oBomQuantity, |* ref
oNumberOfMaterials, |* ref
l.exception.message, |* ref
l.exception.id) <> 0 then |* ref
for l.exception.message.counter = 1 to
Exception.NumberOfMessages(l.exception.id)
Exception.GetMessage(
l.exception.id,
l.exception.message.counter,
l.exception.message) |* ref
dal.set.error.message("@" & l.exception.message)
endfor
Exception.Delete(l.exception.id)
return(DALHOOKERROR)
endif
for l.counter = 1 to oNumberOfMaterials
l.item = oItem(1, l.counter)
l.quantity = oBomQuantity(l.counter)
endfor
free.mem(oProject)
free.mem(oWarehouse)
free.mem(oItem)
free.mem(oCustomizable)
free.mem(oPositionNumber)
free.mem(oBomQuantity)
return(0)
}
OmeLuuk
23rd September 2023, 22:32
The following works for me, e.g., components from two BOM levels are returned, for an item that has the Classic BOM (tibom010). Job Shop by Site is In Preparation and is not Active yet on the environment.
function long public.interface()
{
#pragma used dll "otcextextapi" |* Public Interfaces for tcext
#pragma used dll "otiextbomapi" |* Public Interfaces for tibom
long l.counter
domain tccprj oProject(1) based
domain tccwar oWarehouse(1) based
domain tcitem oItem(1) based
domain tcyesno oCustomizable(1) based
domain tcpono oPositionNumber(1) based
domain tcqiv1 oBomQuantity(1) based
long oNumberOfMaterials
domain tcmcs.str999m l.exception.message
long l.exception.id
long l.exception.message.counter
domain tcitem l.item
domain tcqiv1 l.quantity
if JobShopBillOfMaterial.Explode(
"", |* iSite
"100BX91900002981827", |* iProduct
"", |* iBillOfMaterialCode
"", |* iRevision
0, |* iEffectivityUnit
utc.num(), |* iReferenceDate
10, |* iExplosionDepth
true, |* iMergeComponents
false, |* iApplyScrapYield
true, |* iExplodeLowestPhantoms
oProject, |* ref
oWarehouse, |* ref
oItem, |* ref
oCustomizable, |* ref
oPositionNumber, |* ref
oBomQuantity, |* ref
oNumberOfMaterials, |* ref
l.exception.message, |* ref
l.exception.id) <> 0 then |* ref
for l.exception.message.counter = 1 to
Exception.NumberOfMessages(l.exception.id)
Exception.GetMessage(
l.exception.id,
l.exception.message.counter,
l.exception.message) |* ref
dal.set.error.message("@" & l.exception.message)
endfor
Exception.Delete(l.exception.id)
return(DALHOOKERROR)
endif
for l.counter = 1 to oNumberOfMaterials
l.item = oItem(1, l.counter)
l.quantity = oBomQuantity(l.counter)
endfor
free.mem(oProject)
free.mem(oWarehouse)
free.mem(oItem)
free.mem(oCustomizable)
free.mem(oPositionNumber)
free.mem(oBomQuantity)
return(0)
}I see you depend on the public function to alloc.mem for the array variables but you would have to free.mem them afterwards to avoid memory leak issues. For that reason I would prefer to do the alloc.mem before invoking the public interface function so alloc.mem and free.mem are "on the same level".
RieseUSA
23rd September 2023, 23:23
@OmeLuuk I get your 'on the same level' approach, but I think that it is counterproductive for dynamic arrays. If you do not allocate enough, the called function has to allocate more, if you overollocate, you are wasting memory. Also, the called function might return with an error and no memory allocated. I expect the function to do the memory handling. We all have our programming principles. Anyway, if the discussion was about the same level for db.retry.point() and commit.transaction() calls, I would be in full agreement. I have seen some very bad code in that area.
OmeLuuk
24th September 2023, 10:00
@OmeLuuk I get your 'on the same level' approach, but I think that it is counterproductive for dynamic arrays. If you do not allocate enough, the called function has to allocate more, if you overollocate, you are wasting memory. Also, the called function might return with an error and no memory allocated. I expect the function to do the memory handling. We all have our programming principles. Anyway, if the discussion was about the same level for db.retry.point() and commit.transaction() calls, I would be in full agreement. I have seen some very bad code in that area.
Agreed. In the BOM there is a great level of uncertainty where the array will end, in the price simulator it is a bit different, so there I do the allocation. About the db.retry (and whether or not include updates within the 4GL transaction) fully agreed.
dorleta
25th September 2023, 09:32
Thanks to all for your answers.
My problem really is that the function load correctly for some items and for others only load the first level. I believed that the problem was the way I declared the arrays. I did it of any possible but always with the same result.
In the Job shop material session I can see with the graphic the whole structure of the item but the function in same cases load the item structure in others only the first level.
Thanks
OmeLuuk
26th September 2023, 00:03
Hmmm in that case, could you use a similar (trusted) standard DLL to do the same? Probably there is some kind of reason for it not to show up. It may be effective dates or some other reason, even a software error.
Probably best is to log an incident and/or examine logfiles from the bshell running the function in your BO. There you may find the executed SQL statements and bound variables so you can try to see what is going on.
And update your DLL containing the function, it may be a solved error...