Application Development Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 

SAP Developer Challenge - APIs - Task 2 - Calculate Northbreeze product stock

qmacro
Developer Advocate
Developer Advocate

(Check out the SAP Developer Challenge - APIs blog post for everything you need to know about the challenge to which this task relates!)

In this task you'll move from the public Northwind service to a simple version powered by CAP, and explore data with an OData operation and some system query options.

Background

The OASIS curated Northwind service is great, but it's also sometimes useful to have one's own version. There's an extremely simplified version of the classic Northwind service, called Northbreeze (get it?) at https://developer-challenge.cfapps.eu10.hana.ondemand.com/odata/v4/northbreeze.

This Northbreeze service is powered by the SAP Cloud Application Programming Model (CAP) and offers four entity sets:

  • Products
  • Suppliers
  • Categories
  • Summary of sales by years

(Well there's technically a fifth, TotalProducts, but that's just a calculation projection on the count of products).

The reason for running our own version of Northwind is that we can modify and extend it as we see fit, plus being based on CAP, we can learn about and experiment with CAP's rich support for serving OData APIs.

In this task you'll start to become familiar with the data offered.

Specifically for this task, you'll need to become familiar with the Products data. To do that, have a look at the Northbreeze service's metadata document at https://developer-challenge.cfapps.eu10.hana.ondemand.com/odata/v4/northbreeze/$metadata.

Identify the EntityContainer element that describes the entity sets available, in the form of EntitySet elements, and find the element describing the entity set with the name Products, which should look like this:

<EntitySet Name="Products" EntityType="Northbreeze.Products">
 <NavigationPropertyBinding Path="Category" Target="Categories"/>
 <NavigationPropertyBinding Path="Supplier" Target="Suppliers"/>
</EntitySet>

You can see that this entity set is a collection of Northbreeze.Products entity types. The 'Northbreeze' part is essentially the namespace, generated based on the service name. Follow the trail to the Products entity type, which will be an element outside the EntityContainer element, but still within the Northbreeze-namespaced Schema element.

The Products entity type should look like this:

<EntityType Name="Products">
 <Key>
 <PropertyRef Name="ProductID"/>
 </Key>
 <Property Name="ProductID" Type="Edm.Int32" Nullable="false"/>
 <Property Name="ProductName" Type="Edm.String"/>
 <Property Name="QuantityPerUnit" Type="Edm.String"/>
 <Property Name="UnitPrice" Type="Edm.Decimal" Scale="variable"/>
 <NavigationProperty Name="Category" Type="Northbreeze.Categories" Partner="Products">
 <ReferentialConstraint Property="Category_CategoryID" ReferencedProperty="CategoryID"/>
 </NavigationProperty>
 <Property Name="Category_CategoryID" Type="Edm.Int32"/>
 <NavigationProperty Name="Supplier" Type="Northbreeze.Suppliers" Partner="Products">
 <ReferentialConstraint Property="Supplier_SupplierID" ReferencedProperty="SupplierID"/>
 </NavigationProperty>
 <Property Name="Supplier_SupplierID" Type="Edm.Int32"/>
 <Property Name="UnitsInStock" Type="Edm.Int32"/>
 <Property Name="UnitsOnOrder" Type="Edm.Int32"/>
 <Property Name="ReorderLevel" Type="Edm.Int32"/>
 <Property Name="Discontinued" Type="Edm.Boolean"/>
</EntityType>

Amongst other things, you can see that a product has an ID (ProductID), a name (ProductName), a count of the number of units currently in stock (UnitsInStock) and a boolean that is used to indicate whether or not a product is discontinued (Discontinued).

Request the first few products to see data for these and the other properties, via https://developer-challenge.cfapps.eu10.hana.ondemand.com/odata/v4/northbreeze/Products?$top=5. You should see something like this:

{
 "@odata.context": "$metadata#Products",
 "value": [
 {
 "ProductID": 1,
 "ProductName": "Chai",
 "QuantityPerUnit": "10 boxes x 20 bags",
 "UnitPrice": 18,
 "Category_CategoryID": 1,
 "Supplier_SupplierID": 1,
 "UnitsInStock": 39,
 "UnitsOnOrder": 0,
 "ReorderLevel": 10,
 "Discontinued": false
 },
 {
 "ProductID": 2,
 "ProductName": "Chang",
 "QuantityPerUnit": "24 - 12 oz bottles",
 "UnitPrice": 19,
 "Category_CategoryID": 1,
 "Supplier_SupplierID": 1,
 "UnitsInStock": 17,
 "UnitsOnOrder": 40,
 "ReorderLevel": 25,
 "Discontinued": false
 },
 {
 "ProductID": 3,
 "ProductName": "Aniseed Syrup",
 "QuantityPerUnit": "12 - 550 ml bottles",
 "UnitPrice": 10,
 "Category_CategoryID": 2,
 "Supplier_SupplierID": 1,
 "UnitsInStock": 13,
 "UnitsOnOrder": 70,
 "ReorderLevel": 25,
 "Discontinued": false
 },
 {
 "ProductID": 4,
 "ProductName": "Chef Anton's Cajun Seasoning",
 "QuantityPerUnit": "48 - 6 oz jars",
 "UnitPrice": 22,
 "Category_CategoryID": 2,
 "Supplier_SupplierID": 2,
 "UnitsInStock": 53,
 "UnitsOnOrder": 0,
 "ReorderLevel": 0,
 "Discontinued": false
 },
 {
 "ProductID": 5,
 "ProductName": "Chef Anton's Gumbo Mix",
 "QuantityPerUnit": "36 boxes",
 "UnitPrice": 21.35,
 "Category_CategoryID": 2,
 "Supplier_SupplierID": 2,
 "UnitsInStock": 0,
 "UnitsOnOrder": 0,
 "ReorderLevel": 0,
 "Discontinued": true
 }
 ]
}

Your task

Your task is to calculate the total stock quantity (i.e. the total units in stock) for all current products, i.e. products that are not been marked as discontinued. The result of this calculation should be a number.

Once you have calculated the number, which should be an integer, you should hash it and post the hash as a new reply to this discussion thread, as described in Task 0 - Learn to share your task results and in a similar way to how you've done this in the previous task.

Hints and tips

Like all tasks in this challenge, you are free to approach this one however you see fit. One way would be to request all the products (https://developer-challenge.cfapps.eu10.hana.ondemand.com/odata/v4/northbreeze/Products) and manually sum the values of the relevant UnitsInStock properties.

But where's the fun in that?

How about requesting the entire products entity set in your favorite language and obtaining result by parsing the response and using that language to make the calculation?

You could also use OData's $filter system query option to first reduce the entity set result to only those products that have the value false for the Discontinued property.

And what about the $count facility, which in OData V4 is now a system query option as well something you can append to a resource path?

This would also be a good opportunity to take your first steps exploring some great new OData V4 features supported by CAP, such as data aggregation.

For discussion

How did you approach this task? If you used a programming language, which one did you use, and how did you do it? If you used an $apply based data aggregation feature, what was it, and was was your experience using it?

209 REPLIES 209

Done with $filter. And then ABAP, using class /ui5/cl_json_parser 🙂

-- Tomas --

Great to see folks using ABAP, keep flying the flag! 

cdias
Product and Topic Expert
Product and Topic Expert
0 Kudos

c9624b2663b60b1a1fe82240c7b4a2f615603a765977f56b3811b5b717e6a3a2

cdias
Product and Topic Expert
Product and Topic Expert
0 Kudos

Went for the  $apply approach. Learned something new 😁

qmacro
Developer Advocate
Developer Advocate
0 Kudos

Great to hear!

gustavo-alvarez
Explorer
0 Kudos

03d573f3f38fd3488ad264530e9cdb82ed78a1a33d1b5d3c075d0e9b7aaeb883

geek
Participant
0 Kudos

4941590dae922ec4cce9d4fb3d27195a536b950aa3f0cd16c4bafce1ca5a4757

PriyankaChak
Active Contributor
0 Kudos

61ae3c250e9a7f51c248360d671f2ac711ed42abf081cde9e38c4c39c9bf64a3

SebastianSchuck
Active Participant
0 Kudos

d3c8d8a739cb617f38af7356bf6a015099f6959c51ce14980196fcb98fde2210

TiagoAlmeida
Participant
0 Kudos

de001bee156704e8e83697ec65af29ceed7983cb061234a7530df24a74cc4506

Hello!
Done with an $apply and $filter. 

qmacro
Developer Advocate
Developer Advocate
0 Kudos

Good work @TiagoAlmeida 👍

nmkarthikeya
Active Participant
0 Kudos

f9966f89614c5407b036218cc88aa75f7ace76f8659e2e7f9bc0d1513c5b4a42

Ritik
Participant
0 Kudos

305990f45c7e661d0cf9408371bf819d652b307ac019af5871ee0dcf4d1de0c8

kumarniti4
Product and Topic Expert
Product and Topic Expert
0 Kudos

a260a745d21c636f932d9a1beec8b4a6972868a5227f6c60039be1b441e72d5c

ibibhu
Product and Topic Expert
Product and Topic Expert
0 Kudos

e5ea5a24341209f79b948925c98689c93a61d25095f3344c5f5d43ea7b2c06d8

MioYasutake
Active Contributor
0 Kudos

7d2d4eccba6080e92d84cdcc06a0a0e93a58bf4e4550ce0c91b04f7a6504861c

andyl
Explorer
0 Kudos

46cbf8f1fcd8f1823ec69707aadae08b6de0e830b0e166bf9fc3a86908b1f350

dhegde
Participant
0 Kudos

01b79671b3bdcc09ed051fd976ac7c3e5c3006e24c513af237d4ba02661be5ba

dhegde
Participant

Thanks for the great challenge.  Helped me explore ODATA v4 capabilities further. 

I landed right here https://docs.oasis-open.org/odata/odata-data-aggregation-ext/v4.0/csd04/odata-data-aggregation-ext-v... and read about the available aggregate methods first.  

Used NodeJS to do a GET call with $apply with fitler and aggregate.  To know that I have to pass "/" between `filter` and `aggregate` was a bit tricky.  

dhegde_0-1691548481908.png

To verify my answer, I tried fetching all Products with $filter query option and then used "reduce" to get sum of UnitsInStock

Thank you again!

qmacro
Developer Advocate
Developer Advocate
0 Kudos

Nice work!

BrijeshGandhi
Explorer
0 Kudos

3534e571aa7772b80b735a3212a059a2f561e5f248ddbfadda2d0f4293ea721b

msoans
Explorer
0 Kudos

346dfb024adebc73551f40d2824eb0dff4f94d69baaf44b3c325dc15d0204eab

prachetas
Participant
0 Kudos

55069e3da903369beac98bfe4cbd66882b5d35be0b01e0865f4d2727e496a8ba

ajay_soreng
Developer Advocate
Developer Advocate
0 Kudos

e73e9a3b4f101501afadc0d491338e7b4517c0b58a0330450c338816c7d89feb

Thanks DJ, learned new ways today. I used javascript in postman tests to verify the results and it was fun exploring $apply based data aggregation feature, loved it 😃

qmacro
Developer Advocate
Developer Advocate
0 Kudos

Great to hear, @ajay_soreng !

Ella
Explorer
0 Kudos

de38aafe9cbd435c364d56959794fa6567a206edfbd7db7f55afcafd75140606

jasshauer
Explorer
0 Kudos

316521f1ed5552be82b86f3a75c5d60d121ff68e6af8eda8649a524bb8c7cf6d

i used AI to solve get the result 🙂 Asked chatGPT to sum the result & hash the value as requested - i trained him to do it in ABAP 🙂 

qmacro
Developer Advocate
Developer Advocate
0 Kudos

I'm not sure how I feel about that ... 😉

barisguler
Participant
0 Kudos

deb0e282b99ab15affc7e7de7a7984111dd820de4db989c7dc91fb795483020b

nex
Explorer
0 Kudos

70c7e866339e555a326c60c7d557da87d66cbeb7731ac6d496d270b88e94b074

berserk
Explorer
0 Kudos

bdecc1049120d1f52ca9e0ab5a945fc9f1577e5a4ab48d6bbbba386f43e36ca9

 

RaulVega
Participant
0 Kudos

1e78f0252657c99053c2076283a234ec61728fb4d2434e96a33e8aeb123921d5

mvaibhav
Contributor
0 Kudos

f15266c2188b15a98e7cf5f349389823fb30fe60dfebe621bd5066f3d328112a

MadhavKumar
Explorer
0 Kudos

909d0dd5109505920c94a8be40b78acd5aa548da5d3870a2bcfaa25e1fa4a68f

DenisGaland
Participant
0 Kudos

0c97768c5256af6b93ad8e8cabb44cbb00bcbe152f989d50048b3bf6bb72a161

Naguco
Explorer
0 Kudos

88683208e8f567498a08779b73586ab79045a9c5b896a3baf2e4ad9989924460

Interesting this different approach with aggregations on the query itself, it will saved to me some time if I investigate this before creating my algorithm 😂