Skip to Content

How to make association to BO Material to get the Description.

Hi,

I created custom BO with an association to BO Material.

I also made OVS for field Material ID (which works) and another field Material Description (which does not work, the value does not appear in it).

I tried to make everything by analogy with the Employee association in Car Park example.

node MaterialCosts [0,n] {
element Item			: LANGUAGEINDEPENDENT_MEDIUM_Name;
element MaterialID		: ID;
element MaterialDescription	: LANGUAGEINDEPENDENT_MEDIUM_Name;
element BaseQuantity		: Quantity;
element NoOfPiecePerPack	: Quantity;
element ScrapRate		: Percent;
element Overhead		: Percent;
element TotalQuantity		: Quantity;
element UnitCost		: Amount;
element UoM			: MeasureUnitCode;
element Cost			: Amount;
association ToMaterial [0,1] to Material;
}

What could be the cause?

I see cardinality [0,n] in node Description, is it possible such binding principally?

Or there may be some workaround.

Thank you.

000074.jpg (92.8 kB)
Add comment
10|10000 characters needed characters exceeded

  • Get RSS Feed

6 Answers

  • Best Answer
    Jul 12, 2017 at 08:11 AM

    Hi Aleksi,

    You have to associate through ABSL code.

    something like,

    if(!this.ToMaterial.IsSet()){
    var materialIns = Material.Retrive(this.MaterialID);// you can use query as well.
    if(materialIns.IsSet())
    {
    this.ToMaterial = materialIns;
    }
    }

    Regards

    Senthil

    Add comment
    10|10000 characters needed characters exceeded

  • Jul 13, 2017 at 08:42 PM

    Yet I have found out why the association to Employee in my example did not work.

    It appeared there was a need to add some supporting ABSL code in Event-AfterModify .

    It is just the spot where element ToEmployee is assigned.

    Eventually, final example (after some simplification) looks so

    BO:

    import AP.Common.GDT as apCommonGDT;
    import AP.FO.BusinessPartner.Global;
    import AP.FO.ProductDataMaintenance.Global;
    
    businessobject OVS {
    		element EmployeeID : EmployeeID;
    		element GivenName2 : LANGUAGEINDEPENDENT_MEDIUM_Name;
    		association ToEmployee[0,1] to Employee;
    
    		element MaterialID : ProductInternalID;
    		element Description2 : LANGUAGEINDEPENDENT_MEDIUM_Name;
    		association ToMaterial[0,1] to Material;
    }
    

    Event-AfterModify:

    //	Event: AfterModify 
    import ABSL;
    import AP.FO.BusinessPartner.Global;
    import AP.FO.ProductDataMaintenance.Global;
    
    // Given Name
    // --- cut from CarPark example ---
    // Auxiliary flag that will help us decide whether we have to update the ToEmployee association.
    var bUpdateEmployee = false;
    // Our pointer to the employees' query.
    var qryEmployees;
    // Object that will hold the parameters for our employees' query call.
    var paramEmployee;
    // Collection of result values of our employees' query call.
    var resultEmployees;
    // Check whether our ToEmployee association is still up to date. If not, we'll have to update it.
    if (this.EmployeeID.IsInitial()) {
    	// => No employee indicated for the parking space.
    	if (this.ToEmployee.IsSet()) {
    		// => Our ToEmployee association still holds the employee that had been
    		// associated before - so now we have to reset the association.
    		this.ToEmployee.Reset();
    	}
    }
    else if (!this.ToEmployee.IsSet()) {
    	// => We do have an employee indicated for the parking space, however,
    	// the association ToEmployee hasn't been initialized, yet.
    	// => Set our flag to true.
    	bUpdateEmployee = true;
    }
    else if (this.ToEmployee.IdentificationEmployeeID.EmployeeID.content != this.EmployeeID.content ) {
    	// => We do have an employee indicated for the parking space, however,
    	// the association ToEmployee still holds the employee that had been associated to the space before.
    	// => Set our flag to true.
    	bUpdateEmployee = true;
    }
    if (bUpdateEmployee) {
    	// => Our association to the employee needs to be refreshed.
    	// Reset it first, since the new employee ID might be invalid.
    	this.ToEmployee.Reset();
    	// Now look for the details of the given employee:
    	// ...connect to the BO Employee's query...
    	qryEmployees = Employee.Identification.QueryByEmployeeAttributes;
    	// ...populate the parameters collection for the query call...
    	paramEmployee = qryEmployees.CreateSelectionParams();
    	// ...saying that the ID of the employee we're looking for must be the ID indicated by our user...
    	paramEmployee.Add(qryEmployees.EmployeeID.content, "I", "EQ", this.EmployeeID.content);
    	// ...and execute the query!
    	resultEmployees = qryEmployees.Execute(paramEmployee);
    	// Hopefully we've found an employee to the given ID!
    	foreach (var oneEmployee in resultEmployees) {
    		// Since we know that we can have only one employee to the ID, we
    		// take the first result and exit the loop.
    		this.ToEmployee = oneEmployee.ToRoot;
    		break;
    	}
    }
    // --- cut from CarPark example ---
    
    
    // Given Name 2
    var employeeidentification = Employee.Identification.Retrieve ( this.EmployeeID );
    if ( employeeidentification.IsSet() ) {
    	this.GivenName2 = employeeidentification.ToParent.CurrentCommon.Person.Name.GivenName;
    } else {
    	this.GivenName2.Clear();
    }
    
    // Description (not implemented)
    
    
    // Description 2
    var material = Material.Retrieve ( this.MaterialID );
    if ( material.IsSet() ) {
    	this.Description2 = material.Description.GetFirst().Description.content;
    } else {
    	this.Description2.Clear();
    }
    
    return;
    

    Result:

    It seems everything works properly now.

    Best regards,

    Aleksei

    Add comment
    10|10000 characters needed characters exceeded

  • Jul 12, 2017 at 10:38 AM

    Thank you, Senthil,

    As far as I understand this code should be put in After-Modify event?

    I thought over such a way to remove association at all (there will not be a need the association in this case) and just to retrieve Description with a query (it is a common practice in ABAP). Only I am not sure about performance in ByD as a web application. But I will try that anyway.

    Thank you.

    Aleksei

    Add comment
    10|10000 characters needed characters exceeded

    • Yes Aleksei,

      Association always cost performance, If showing description for any material ID is your only goal, I would suggest add one more element in the BO and assign the description to it. so that you can cut the performance cost.

      Regards,

      Senthil.

  • Jul 13, 2017 at 08:13 AM

    Thank you, Senthil,

    I tried getting data with using ABSL, and it works quite fast.

    There is a workable example I have made to get GivenName for Employee and Description for Material

    BO:

    import AP.Common.GDT as apCommonGDT;
    import AP.FO.BusinessPartner.Global;
    import AP.FO.ProductDataMaintenance.Global;
    
    businessobject OVS {
    
    		element EmployeeID : EmployeeID;
    		element GivenName2 : LANGUAGEINDEPENDENT_MEDIUM_Name;
    		association ToEmployee[0,1] to Employee;
    
    
    		element MaterialID : ProductInternalID;
    		element Description2 : LANGUAGEINDEPENDENT_MEDIUM_Name;
    		association ToMaterial[0,1] to Material;
    
    
    		node Employees[0,n] {
    			element Workplace : ID;
    			element EmployeeID : ID;
    			association ToEmployee[0,1] to Employee;
    		}
    }
    

    Event-AfterModify.absl:

    *
    	Add your SAP Business ByDesign scripting language implementation for:
    		Business Object: OVS
    		Node: Root
    		Event: AfterModify 
    		
    	Note: 
    	  - To access the elements of the business object node, 
    	    use path expressions, for example, this.<element name>. 
    	  - To use code completion, press CTRL+J. 
    	  - The solution uses this script if:
    		- the value of any field in the node in which this script is contained is modified.
    		- the node itself is modified by another business object within the same solution.
    */
    
    
    import ABSL;
    import AP.FO.BusinessPartner.Global;
    import AP.FO.ProductDataMaintenance.Global;
    
    var employeeidentification = Employee.Identification.Retrieve ( this.EmployeeID );
    if ( employeeidentification.IsSet() ) {
    	this.GivenName2 = employeeidentification.ToParent.CurrentCommon.Person.Name.GivenName;
    } else {
    	this.GivenName2.Clear();
    }
    
    
    var material = Material.Retrieve ( this.MaterialID );
    if ( material.IsSet() ) {
    	this.Description2 = material.Description.GetFirst().Description.content;
    } else {
    	this.Description2.Clear();
    }
    
    
    return;
    
    

    QA screen:

    As far as we can see Given Name and Description implemented with the association are populated neither in the Root node nor in the Employees node. I have no idea why the Employee association has stopped working. I have made the example according to Car Park example exactly. ABSL implemented Given Name 2 and Description 2 work properly and do not need the associations at all.

    Thank you.

    Aleksei

    Add comment
    10|10000 characters needed characters exceeded

  • Jul 13, 2017 at 09:00 AM

    Thank you, Horst, for useful information.

    Unfortunately, now associations do not work in my example, even the Employee association has stopped working. It keeps working normally in my old Car Park examples, though. I have no idea what the cause is.

    I have read the blog but, unfortunately, so far I could not realise where the filter for the association is.

    It is not quite clear to me how associations work in general - how a master field is chosen to link with associated BO.

    For example, if we have both Employee1 : ID and Employee2 : ID elements in our BO what element will be chosen as a master key for the association ToEmployee? Where could I see this binding in properties?

    Besides that, I seem there is a small typo in Cloud Application Studio documentation (studio_od_1611.pdf, studio_od_1702.pdf) a picture on page 96 in the Car Park example. I rounded it.

    Probably it should be CurrentCommon. If so, please, fix it in next version of the manual. Everything is correct in the document text, though.

    Thank you.

    Aleksei

    Add comment
    10|10000 characters needed characters exceeded

    • Hello Horst,

      Thank you. Yes, it is just the cause why my example did not work.

      I forgot to create ABSL script for the association.

      Now everything is OK. I have figured out how associations work.

      Best regards,

      Aleksei

  • Jul 12, 2017 at 12:36 PM

    Hello Aleksi

    From your statement

    "OVS for field Material ID (which works) and another field Material Description (which does not work)"

    I assume its the OVS which returns values for the ID but no for the description.

    This is because - as you already suggest - the association to the Description node is a 1-to-many. This means it returns a list of descriptions (in different languages).

    Have a look at this blog.

    There is a filter for this association in which you can provide the language. Then only one value is returned and the OVS should work.

    HTH,
    . Horst

    Add comment
    10|10000 characters needed characters exceeded