
namespace my.app;
entity Salesorder{
Key salesOrderID : String;
customer : String;
orderDate : DateTime;
Salesorderitem : Composition of many Salesorderitem on Salesorderitem.salesOrder = $self;
}
entity Salesorderitem{
Key itemID : Integer;
Key salesOrder : Association to Salesorder @Common.Label: 'Sales Order ID' @Common.FieldControl: #Hidden;
productID : String;
productDescription : String;
quantity : Decimal(12,3);
quantityUOM : String;
confirmedQuantity : Decimal(12,3);
confirmedQuantityUOM : String;
price: Decimal(12,3);
currency: String(3);
}
using my.app from '../db/data-model';
service Salesorderhandling {
@insertonly entity Salesorder as projection on app.Salesorder;
@insertonly entity Salesorderitem as projection on app.Salesorderitem{
*
} actions {
action CheckATP( ) returns String(255);
};
}
<edmx:Edmx xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" Version="1.0">
<edmx:DataServices xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:DataServiceVersion="1.0">
<Schema xmlns="http://schemas.microsoft.com/ado/2008/09/edm" xmlns:sap="http://www.sap.com/Protocols/SAPData" xmlns:c4c="http://www.sap.com/Protocols/C4CData" Namespace="cust">
<EntityType Name="Material">
<Key>
<PropertyRef Name="ObjectID"/>
</Key>
<Property Name="ObjectID" Type="Edm.String" Nullable="false" MaxLength="70" FixedLength="true" sap:creatable="false" sap:updatable="false" sap:filterable="true"/>
<Property Name="UUID" Type="Edm.Guid" Nullable="true" sap:creatable="false" sap:updatable="false" sap:filterable="true"/>
<Property Name="InternalID" Type="Edm.String" Nullable="true" MaxLength="40" FixedLength="true" sap:creatable="true" sap:updatable="true" sap:filterable="true"/>
<Property Name="Description" Type="Edm.String" Nullable="true" MaxLength="40" FixedLength="true" sap:creatable="true" sap:updatable="true" sap:filterable="true"/>
<Property Name="DescriptionlanguageCode" Type="Edm.String" Nullable="true" MaxLength="2" FixedLength="true" sap:creatable="true" sap:updatable="true" sap:filterable="true" c4c:value-help="MaterialDescriptionlanguageCodeCollection" sap:text="DescriptionlanguageCodeText"/>
<Property Name="DescriptionlanguageCodeText" Type="Edm.String" Nullable="true" sap:creatable="false" sap:updatable="false" sap:filterable="true"/>
<Property Name="BaseMeasureUnitCode" Type="Edm.String" Nullable="true" MaxLength="3" FixedLength="true" sap:creatable="true" sap:updatable="true" sap:filterable="true" c4c:value-help="MaterialBaseMeasureUnitCodeCollection" sap:text="BaseMeasureUnitCodeText"/>
<Property Name="BaseMeasureUnitCodeText" Type="Edm.String" Nullable="true" sap:creatable="false" sap:updatable="false" sap:filterable="true"/>
</EntityType>
<EntityType Name="CodeList">
<Key>
<PropertyRef Name="Code"/>
</Key>
<Property Name="Code" Type="Edm.String" Nullable="false" FixedLength="false" sap:creatable="false" sap:updatable="false" sap:filterable="true"/>
<Property Name="Description" Type="Edm.String" Nullable="false" FixedLength="false" sap:creatable="false" sap:updatable="false" sap:filterable="true"/>
</EntityType>
<EntityContainer Name="byd_product" m:IsDefaultEntityContainer="true">
<EntitySet Name="MaterialBaseMeasureUnitCodeCollection" EntityType="cust.CodeList" sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:semantics="fixed-values"/>
<EntitySet Name="MaterialCollection" EntityType="cust.Material" sap:creatable="true" sap:updatable="true" sap:deletable="true"/>
<EntitySet Name="MaterialDescriptionlanguageCodeCollection" EntityType="cust.CodeList" sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:semantics="fixed-values"/>
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
Parameter | Value |
---|---|
User ID | User ID of your SAP CP NEO subaccount |
Password | Password of your SAP CP NEO subaccount |
Name | Name of Destination e.g. ByDSyS1 |
Description | Description of the Destination (optional) |
Proxy Type | Internet |
URL | https://my<ByD tenantname>.sapbydesign.com |
Authentication | BasicAuthentication |
Username | User ID of your SAP ByD tenant |
Password | Password of your SAP ByD tenant |
Additionally Java virtual data model (VDM) classes are generated. These classes provide fluent and type-safe java APIs to build queries and access SAP ByD OData endpoints.
using my.app from '../db/data-model';
using cust as cust_API_product from './external/csn/byd_product';
service Salesorderhandling {
@insertonly entity Salesorder as projection on app.Salesorder;
@insertonly entity Salesorderitem as projection on app.Salesorderitem{
*
} actions {
action CheckATP( ) returns String(255);
};
@cds.persistence.skip
Entity Products as projection on cust_API_product.Material {
key ObjectID as ObjectID,
InternalID as InternalID,
Description as Description
};
}
package my.company;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.sap.cloud.sdk.odatav2.connectivity.ODataException;
import com.sap.cloud.sdk.s4hana.connectivity.ErpConfigContext;
import com.sap.cloud.sdk.service.prov.api.operations.Query;
import com.sap.cloud.sdk.service.prov.api.request.QueryRequest;
import com.sap.cloud.sdk.service.prov.api.response.QueryResponse;
import com.sap.cloud.sdk.service.prov.api.response.ErrorResponse;
import vdm.services.DefaultBydProductService;
import vdm.namespaces.bydproduct.Material;
public class ProductRemoteHandler {
private static final Logger logger = LoggerFactory.getLogger(ProductRemoteHandler.class);
private static final String DESTINATION_NAME = "bydsystem";
@Query(serviceName = "Salesorderhandling", entity = "Products")
public QueryResponse queryProducts(QueryRequest qryRequest) {
try {
List<Material> products = new DefaultBydProductService()
.withServicePath("/sap/byd/odata/cust/v1/byd_product").getAllMaterial()
.select(Material.OBJECT_ID, Material.INTERNAL_ID, Material.DESCRIPTION)
.execute(new ErpConfigContext(DESTINATION_NAME));
QueryResponse queryResponse = QueryResponse.setSuccess().setData(products).response();
return queryResponse;
} catch (final ODataException e) {
logger.error("==> Exception calling backend OData V2 service for Query of Products: " + e.getMessage(), e);
logger.error("==> Exception calling backend additional data: " + e.getLocalizedMessage());
ErrorResponse errorResponse = ErrorResponse.getBuilder()
.setMessage("There is an error. Check the logs for the details.").setStatusCode(500).setCause(e)
.response();
QueryResponse queryResponse = QueryResponse.setError(errorResponse);
return queryResponse;
}
}
}
package my.company;
import java.util.Map;
import java.util.Random;
import java.util.Arrays;
import com.sap.cloud.sdk.service.prov.api.exception.*;
import com.sap.cloud.sdk.service.prov.api.EntityData;
import com.sap.cloud.sdk.service.prov.api.DataSourceHandler;
import com.sap.cloud.sdk.service.prov.api.ExtensionHelper;
import com.sap.cloud.sdk.service.prov.api.annotations.Action;
import com.sap.cloud.sdk.service.prov.api.request.OperationRequest;
import com.sap.cloud.sdk.service.prov.api.response.OperationResponse;
public class ATPCheckHandler {
@Action(Name = "Salesorderitem_CheckATP", serviceName = "Salesorderhandling")
public OperationResponse checkATP(OperationRequest actionRequest, ExtensionHelper extensionHelper) {
Map<String, Object> keys = actionRequest.getParameters();
DataSourceHandler handler = extensionHelper.getHandler();
try {
// Get Item Data
EntityData entityData = handler.executeRead("Salesorderitem", keys,
Arrays.asList("itemID", "salesOrder_salesOrderID", "productID", "quantity", "quantityUOM",
"confirmedQuantity", "confirmedQuantityUOM", "price", "currency"));
// Calculate confirmed quantity (Random value between 0 and Requested Quantity)
double requestedQuantity = Double.parseDouble(entityData.getElementValue("quantity").toString());
double confirmedQuantity = new Random().nextInt((int) requestedQuantity + 1);
String confirmedQuantityUom = entityData.getElementValue("quantityUOM").toString();
// Write confirmed quantity
entityData = EntityData.getBuilder(entityData).removeElement("confirmedQuantity")
.addElement("confirmedQuantity", confirmedQuantity).removeElement("confirmedQuantityUOM")
.addElement("confirmedQuantityUom", confirmedQuantityUom).buildEntityData("Salesorderitem");
handler.executeUpdate(entityData, keys, false);
String result = entityData.getElementValue("salesOrder_salesOrderID").toString() + "-"
+ entityData.getElementValue("itemID").toString();
OperationResponse response = OperationResponse.setSuccess().setPrimitiveData(Arrays.asList(result))
.response();
;
return response;
} catch (DatasourceException e) {
return null;
}
}
}
SAP Fiori UIs are defined by OData Annotations. In this section, we will see how to add UI annotations using CDS models. However, UI annotations can also be added using the annotation modeler of SAP Web IDE.
using Salesorderhandling from './my-service';
annotate Salesorderhandling.Products with {
ObjectID
@Common.Label: 'Node ID'
@Common.FieldControl: #Hidden;
InternalID
@title : 'Product ID';
Description
@title : 'Description';
};
annotate Salesorderhandling.Products with @(
UI.Identification:
[ {$Type: 'UI.DataField', Value: InternalID},
{$Type: 'UI.DataField', Value: Description},
]
);
annotate Salesorderhandling.Salesorder with {
salesOrderID
@Common.Label : 'Sales Order ID';
customer
@Common.Label : 'Customer';
orderDate
@Common.Label : 'Ordered On';
};
annotate Salesorderhandling.Salesorder with @(
UI.LineItem: [
{$Type: 'UI.DataField', Value: salesOrderID},
{$Type: 'UI.DataField', Value: customer},
{$Type: 'UI.DataField', Value: orderDate},
],
UI.HeaderInfo: {
Title: { Value: salesOrderID },
TypeName:'Sales Order',
TypeNamePlural:'Sales Orders'
},
UI.Identification:
[
{$Type: 'UI.DataField', Value: salesOrderID},
{$Type: 'UI.DataField', Value: customer},
{$Type: 'UI.DataField', Value: orderDate}
],
UI.Facets:
[
{
$Type:'UI.CollectionFacet',
Facets: [
{ $Type:'UI.ReferenceFacet', Label: 'General Info', Target: '@UI.Identification' }
],
Label:'Order Details',
},
{$Type:'UI.ReferenceFacet', Label: 'Sales Order Items', Target: 'Salesorderitem/@UI.LineItem'},
]
);
annotate Salesorderhandling.Salesorderitem with {
itemID
@Common.Label: 'Item ID';
productID
@Common.Label : 'Product ID'
@sap.value.list: 'Products'
@Common.ValueList: {
entity: 'Products',
Label: 'Products',
SearchSupported: 'true',
Parameters: [
{ $Type: 'Common.ValueListParameterInOut', LocalDataProperty: 'productID', ValueListProperty: 'InternalID', Label: 'Product ID' },
{ $Type: 'Common.ValueListParameterInOut', LocalDataProperty: 'productDescription', ValueListProperty: 'Description', Label: 'Description'},
]
};
productDescription
@Common.Label : 'Product Description'
@Common.FieldControl: #ReadOnly;
quantity
@Common.Label: 'Quantity ';
quantityUOM
@Common.Label: 'Quantity UoM ';
confirmedQuantity
@Common.Label: 'Confirmed Quantity '
@Common.FieldControl: #ReadOnly;
confirmedQuantityUOM
@Common.Label: 'Confirmed Quantity UoM '
@Common.FieldControl: #ReadOnly;
price
@Common.Label: 'Price';
currency
@Common.Label: 'Currency';
};
annotate Salesorderhandling.Salesorderitem with @(
UI.LineItem: [
{$Type: 'UI.DataFieldForAction', Action: 'Salesorderhandling.EntityContainer/Salesorderitem_CheckATP', Label: 'Check ATP', Visible, Enabled},
{$Type: 'UI.DataField', Value: salesOrder_salesOrderID },
{$Type: 'UI.DataField', Value: itemID},
{$Type: 'UI.DataField', Value: productID},
{$Type: 'UI.DataField', Value: productDescription},
{$Type: 'UI.DataField', Value: quantity},
{$Type: 'UI.DataField', Value: quantityUOM},
{$Type: 'UI.DataField', Value: price},
{$Type: 'UI.DataField', Value: currency},
{$Type: 'UI.DataField', Value: confirmedQuantity},
{$Type: 'UI.DataField', Value: confirmedQuantityUOM},
],
UI.HeaderInfo: {
Title: { Value: itemID },
TypeName:'Sales Order Item',
TypeNamePlural:'Sales Order Items'
},
UI.Facets: [
{
$Type:'UI.CollectionFacet',
Facets:[
{ $Type: 'UI.ReferenceFacet', Label: 'General Info', Target: '@UI.FieldGroup#GeneralInfo' },
{ $Type: 'UI.ReferenceFacet', Label: 'Quantity Info', Target: '@UI.FieldGroup#Quantity' },
{ $Type: 'UI.ReferenceFacet', Label: 'Price Info', Target: '@UI.FieldGroup#Price' },
],
Label:'Item Details',
}
],
UI.FieldGroup#GeneralInfo: {
Label: 'General Info',
Data: [
{$Type: 'UI.DataField', Value: salesOrder_salesOrderID },
{$Type: 'UI.DataField', Value: itemID},
{$Type: 'UI.DataField', Value: productID},
{$Type: 'UI.DataField', Value: productDescription}
]
},
UI.FieldGroup#Quantity: {
Label: 'Quantity Info',
Data: [
{$Type: 'UI.DataField', Value: quantity},
{$Type: 'UI.DataField', Value: quantityUOM},
{$Type: 'UI.DataField', Value: confirmedQuantity},
{$Type: 'UI.DataField', Value: confirmedQuantityUOM},
]
},
UI.FieldGroup#Price: {
Label: 'Price Info',
Data: [
{$Type: 'UI.DataField', Value: price},
{$Type: 'UI.DataField', Value: currency},
]
},
);
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
31 | |
5 | |
4 | |
3 | |
3 | |
3 | |
2 | |
2 | |
2 | |
2 |